如題:
返回的數據源是以List<T>表示,但因需要在DataGridView中單擊列標題進行排序,所以寫了一個繼承於BindingList<T>的類SortableBindingList<T> 。在remoting客戶端調用遠程對象時,如果數據源返回結果是List<T>則沒問題,如果是SortableBindingList<T>則提示以下錯誤:The type System.ComponentModel.PropertyDescriptor is not ed as serializable。應該時序列化的問題吧!以下為代碼
[Serializable]
public class SortableBindingList<T> : BindingList<T>
{
private bool isSortedCore = true;
private ListSortDirection sortDirectionCore = ListSortDirection.Ascending;
private PropertyDescriptor sortPropertyCore = null;
private string defaultSortItem; public SortableBindingList() : base()
{
} public SortableBindingList(IList<T> list) : base(list) { }
protected override bool SupportsSortingCore
{
get { return true; }
} protected override bool SupportsSearchingCore
{
get { return true; }
} protected override bool IsSortedCore
{
get { return isSortedCore; }
} protected override ListSortDirection SortDirectionCore
{
get { return sortDirectionCore; }
} protected override PropertyDescriptor SortPropertyCore
{
get { return sortPropertyCore; }
} protected override int FindCore(PropertyDescriptor prop, object key)
{
for (int i = 0; i < this.Count; i++)
{
if (Equals(prop.GetValue(this[i]), key)) return i;
}
return -1;
} protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
isSortedCore = true;
sortPropertyCore = prop;
sortDirectionCore = direction;
Sort();
} protected override void RemoveSortCore()
{
if (isSortedCore)
{
isSortedCore = false;
sortPropertyCore = null;
sortDirectionCore = ListSortDirection.Ascending;
Sort();
}
} public string DefaultSortItem
{
get { return defaultSortItem; }
set
{
if (defaultSortItem != value)
{
defaultSortItem = value;
Sort();
}
}
} private void Sort()
{
List<T> list = (this.Items as List<T>);
list.Sort(CompareCore);
ResetBindings();
} private int CompareCore(T o1, T o2)
{
int ret = 0;
if (SortPropertyCore != null)
{
ret = CompareValue(SortPropertyCore.GetValue(o1), SortPropertyCore.GetValue(o2), SortPropertyCore.PropertyType);
}
if (ret == 0 && DefaultSortItem != null)
{
PropertyInfo property = typeof(T).GetProperty(DefaultSortItem, BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.IgnoreCase, null, null, new Type[0], null);
if (property != null)
{
ret = CompareValue(property.GetValue(o1, null), property.GetValue(o2, null), property.PropertyType);
}
}
if (SortDirectionCore == ListSortDirection.Descending) ret = -ret;
return ret;
} private static int CompareValue(object o1, object o2, Type type)
{
//定义的比较
if (o1 == null)
return o2 == null ? 0 : -1;
else if (o2 == null)
return 1;
else if (type.IsPrimitive || type.IsEnum)
return Convert.ToDouble(o1).CompareTo(Convert.ToDouble(o2));
else if (type == typeof(DateTime))
return Convert.ToDateTime(o1).CompareTo(o2);
else if (type == typeof(decimal))
return Convert.ToDecimal(o1).CompareTo(o2);
else
return String.Compare(o1.ToString().Trim(), o2.ToString().Trim());
}
}
}謝謝!如有代碼更佳!
返回的數據源是以List<T>表示,但因需要在DataGridView中單擊列標題進行排序,所以寫了一個繼承於BindingList<T>的類SortableBindingList<T> 。在remoting客戶端調用遠程對象時,如果數據源返回結果是List<T>則沒問題,如果是SortableBindingList<T>則提示以下錯誤:The type System.ComponentModel.PropertyDescriptor is not ed as serializable。應該時序列化的問題吧!以下為代碼
[Serializable]
public class SortableBindingList<T> : BindingList<T>
{
private bool isSortedCore = true;
private ListSortDirection sortDirectionCore = ListSortDirection.Ascending;
private PropertyDescriptor sortPropertyCore = null;
private string defaultSortItem; public SortableBindingList() : base()
{
} public SortableBindingList(IList<T> list) : base(list) { }
protected override bool SupportsSortingCore
{
get { return true; }
} protected override bool SupportsSearchingCore
{
get { return true; }
} protected override bool IsSortedCore
{
get { return isSortedCore; }
} protected override ListSortDirection SortDirectionCore
{
get { return sortDirectionCore; }
} protected override PropertyDescriptor SortPropertyCore
{
get { return sortPropertyCore; }
} protected override int FindCore(PropertyDescriptor prop, object key)
{
for (int i = 0; i < this.Count; i++)
{
if (Equals(prop.GetValue(this[i]), key)) return i;
}
return -1;
} protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
isSortedCore = true;
sortPropertyCore = prop;
sortDirectionCore = direction;
Sort();
} protected override void RemoveSortCore()
{
if (isSortedCore)
{
isSortedCore = false;
sortPropertyCore = null;
sortDirectionCore = ListSortDirection.Ascending;
Sort();
}
} public string DefaultSortItem
{
get { return defaultSortItem; }
set
{
if (defaultSortItem != value)
{
defaultSortItem = value;
Sort();
}
}
} private void Sort()
{
List<T> list = (this.Items as List<T>);
list.Sort(CompareCore);
ResetBindings();
} private int CompareCore(T o1, T o2)
{
int ret = 0;
if (SortPropertyCore != null)
{
ret = CompareValue(SortPropertyCore.GetValue(o1), SortPropertyCore.GetValue(o2), SortPropertyCore.PropertyType);
}
if (ret == 0 && DefaultSortItem != null)
{
PropertyInfo property = typeof(T).GetProperty(DefaultSortItem, BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.IgnoreCase, null, null, new Type[0], null);
if (property != null)
{
ret = CompareValue(property.GetValue(o1, null), property.GetValue(o2, null), property.PropertyType);
}
}
if (SortDirectionCore == ListSortDirection.Descending) ret = -ret;
return ret;
} private static int CompareValue(object o1, object o2, Type type)
{
//定义的比较
if (o1 == null)
return o2 == null ? 0 : -1;
else if (o2 == null)
return 1;
else if (type.IsPrimitive || type.IsEnum)
return Convert.ToDouble(o1).CompareTo(Convert.ToDouble(o2));
else if (type == typeof(DateTime))
return Convert.ToDateTime(o1).CompareTo(o2);
else if (type == typeof(decimal))
return Convert.ToDecimal(o1).CompareTo(o2);
else
return String.Compare(o1.ToString().Trim(), o2.ToString().Trim());
}
}
}謝謝!如有代碼更佳!
[Serializable]
public class SortableBindingList<T> : BindingList<T>
{
private bool isSortedCore = true;
private ListSortDirection sortDirectionCore = ListSortDirection.Ascending;
private PropertyDescriptor sortPropertyCore = null;
private string defaultSortItem; public SortableBindingList() : base()
{
} public SortableBindingList(IList<T> list) : base(list) { }
protected override bool SupportsSortingCore
{
get { return true; }
} protected override bool SupportsSearchingCore
{
get { return true; }
} protected override bool IsSortedCore
{
get { return isSortedCore; }
} protected override ListSortDirection SortDirectionCore
{
get { return sortDirectionCore; }
} protected override PropertyDescriptor SortPropertyCore
{
get { return sortPropertyCore; }
} protected override int FindCore(PropertyDescriptor prop, object key)
{
for (int i = 0; i < this.Count; i++)
{
if (Equals(prop.GetValue(this[i]), key)) return i;
}
return -1;
} protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
isSortedCore = true;
sortPropertyCore = prop;
sortDirectionCore = direction;
Sort();
} protected override void RemoveSortCore()
{
if (isSortedCore)
{
isSortedCore = false;
sortPropertyCore = null;
sortDirectionCore = ListSortDirection.Ascending;
Sort();
}
} public string DefaultSortItem
{
get { return defaultSortItem; }
set
{
if (defaultSortItem != value)
{
defaultSortItem = value;
Sort();
}
}
} private void Sort()
{
List<T> list = (this.Items as List<T>);
list.Sort(CompareCore);
ResetBindings();
} private int CompareCore(T o1, T o2)
{
int ret = 0;
if (SortPropertyCore != null)
{
ret = CompareValue(SortPropertyCore.GetValue(o1), SortPropertyCore.GetValue(o2), SortPropertyCore.PropertyType);
}
if (ret == 0 && DefaultSortItem != null)
{
PropertyInfo property = typeof(T).GetProperty(DefaultSortItem, BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.IgnoreCase, null, null, new Type[0], null);
if (property != null)
{
ret = CompareValue(property.GetValue(o1, null), property.GetValue(o2, null), property.PropertyType);
}
}
if (SortDirectionCore == ListSortDirection.Descending) ret = -ret;
return ret;
} private static int CompareValue(object o1, object o2, Type type)
{
//定义的比较
if (o1 == null)
return o2 == null ? 0 : -1;
else if (o2 == null)
return 1;
else if (type.IsPrimitive || type.IsEnum)
return Convert.ToDouble(o1).CompareTo(Convert.ToDouble(o2));
else if (type == typeof(DateTime))
return Convert.ToDateTime(o1).CompareTo(o2);
else if (type == typeof(decimal))
return Convert.ToDecimal(o1).CompareTo(o2);
else
return String.Compare(o1.ToString().Trim(), o2.ToString().Trim());
}
}
是自定义的泛型类.要注意一下注册方式.
因为是自定义的类,所以在两端是不允许自动序列化和反序列化的,在注册时在两端将自动级别设为FULL.
下为说明(源于vs随机文档):
依赖于运行时类型验证的远程处理系统必须反序列化一个远程流,然后才能开始使用它,未经授权的客户端可能会试图利用反序列化这一时机。为了免受这种攻击,.NET Framework 远程处理提供了两个自动反序列化级别:Low 和 Full。Low(默认值)防止反序列化攻击的方式是:在反序列化时,只处理与最基本的远程处理功能关联的类型,如自动反序列化远程处理基础结构类型、有限的系统实现类型集和基本的自定义类型集。Full 反序列化级别支持远程处理在所有情况下支持的所有自动反序列化类型。 警告
不要以为控制反序列化是应用程序要求的唯一安全机制。在分布式应用程序中,即使严格控制序列化也不能防止这种危险的发生:即未经授权的客户端截获通信内容,然后以某种方式利用该通信内容,即使只是向其他用户显示数据,也会造成损害。因此,虽然 Low 反序列化级别对某些基于自动反序列化的攻击类型提供了一定的保护,但仍然必须评估是否使用身份验证和加密方法来帮助保护您的数据。有关详细信息,请参见安全性。
下面的列表描述 .NET Framework 远程处理反序列化级别:Low(默认级别).NET Framework 远程处理中的默认反序列化级别支持以下类型的反序列化:远程处理基础结构对象。它们是在基本级别进行远程处理时所需的类型。基元类型以及由基元类型构成的引用类型和值类型。用 SerializableAttribute 属性标记但未实现 ISerializable 接口的引用类型和值类型。实现 ISerializable 并且未发出序列化之外的其他任何要求的系统提供类型。 具有强名称并且位于未用 AllowPartiallyTrustedCallersAttribute 属性标记的程序集中的自定义类型。实现 ISerializable 并且未发出序列化之外的其他任何要求的自定义类型。实现 ILease 接口并且不属于 MarshalByRefObject 对象的类型。用于激活(以支持客户端激活的对象)的 ObjRef 对象;也就是说,客户端可以反序列化返回的 ObjRef,但服务器却不能。Full .NET Framework 远程处理中的 Full 反序列化级别支持其他所有方案,包括以下附加类型的反序列化:作为参数传递的 ObjRef 对象。实现 ISponsor 接口的对象。由 IContributeEnvoySink 接口在代理和客户端管道之间插入的对象。作为参数传递的委托类型。从作为参数传递的 MarshalByRefObject 继承的对象。作为参数传递的 ISerializable 类型。在 GAC 中存储并且未用 AllowPartiallyTrustedCallersAttribute 属性标记的类型。如果应用程序要求使用仅在 Full 反序列化级别才可用的远程处理功能,您必须提供身份验证的类型和必要的加密级别,以保护任何在使用远程方案中的这些高级功能时可能遭受风险的资源。 您可以通过编程方式或使用应用程序配置文件设置反序列化级别。以编程方式设置反序列化级别
要以编程方式设置反序列化级别,请在创建时将以下属性传递给 SoapServerFormatterSinkProvider 对象或 BinaryServerFormatterSinkProvider 对象。然后,当该值插入到接收链中时,远程处理系统将在格式化程序上设置该值。以下示例说明如何在宿主应用程序域中将反序列化级别设置为 Full。 C# 复制代码
// Creating a custom formatter for a TcpChannel sink chain.
BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
provider.TypeFilterLevel = TypeFilterLevel.Full;
// Creating the IDictionary to set the port on the channel instance.
IDictionary props = new Hashtable();
props["port"] = 8085;
// Pass the properties for the port setting and the server provider in the server chain argument. (Client remains null here.)
TcpChannel chan = new TcpChannel(props, null, provider);
Visual Basic 复制代码
' Creating a custom formatter for your TcpChannel sink chain.
Dim provider As New BinaryServerFormatterSinkProvider()
provider.TypeFilterLevel = TypeFilterLevel.Full
' Creating the IDictionary to set the port on the channel instance.
Dim props As IDictionary = New Hashtable()
props("port") = 8085
' Pass the properties for the port setting and the server provider in the server chain argument. (Client remains null here.)
Dim chan As New TcpChannel(props, DBNull.Value, provider)
使用应用程序配置文件设置反序列化级别
要使用配置文件设置反序列化级别,必须显式指定 <formatter> 元素的 typeFilterLevel 属性。虽然这通常是在服务器端指定的,但您还必须为注册来侦听回调的客户端上的任何信道指定这一属性,以控制其反序列化级别。以下示例为应用程序域中的 SoapFormatter 和 BinaryFormatter 显式地将反序列化级别设置为 Low。 复制代码
<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown
type="ServiceType, common"
objectUri="ServiceType.soap"
mode="Singleton"
/>
</service>
<channels>
<channel ref="http">
<serverProviders>
<provider ref="wsdl" />
<formatter ref="soap" typeFilterLevel=Low />
<formatter ref="binary" typeFilterLevel=Low />
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>
[Serializable]
public class SortableBindingList <T> : BindingList <T>
{
[NonSerialized]
private PropertyDescriptor sortPropertyCore = null;
protected override PropertyDescriptor SortPropertyCore
{
get { return sortPropertyCore; }
}
}