AC.*_*AC. 8 c# reflection serialization json
我正在寻找更通用/"标准"的方式来从一组对字符串,对象实例化某种类型T的对象.对我来说,看起来应该有一些众所周知的方法,但我找不到它,所以我想出了这段代码.有人知道更好的事吗?
// usage
public class test
{
public int field1;
public string field2;
public bool field3;
public string[] field4;
public IDictionary<string,object> field5 { get; set; }
public static IDictionary<string,object> dynamic()
{
return new Dictionary<string,object>{
{ "field1", 2 },
{ "field2", "string" },
{ "field3", true },
{ "field4", new[] { "id3", "id4", "id5" } },
{ "field5", new Dictionary<string,object>{ { "id1", "" } } }
};
}
}
...
var r = new dynamic_data_serializer<test>().create( test.dynamic() );
...
//
public class dynamic_data_serializer< T >
{
public T create( object obj )
{
var result = default(T);
if ( obj == null )
return result;
var ttype = typeof(T);
var objtype = obj.GetType();
if ( ttype.IsAssignableFrom( objtype ) ) {
result = (T)obj;
return result;
}
if ( ttype.IsClass ) { // custom classes, array, dictionary, etc.
result = Activator.CreateInstance<T>();
if ( objtype == typeof(IDictionary<string,object>) ||
objtype == typeof(Dictionary<string,object>) ) {
var obj_as_dict = obj as IDictionary<string,object>;
var fields = ttype.GetFields();
if ( fields.Length > 0 )
set_fields_from( result, fields, obj_as_dict );
var properties = ttype.GetProperties();
if ( properties.Length > 0 )
set_properties_from( result, properties, obj_as_dict );
}
}
return result;
}
private void set_fields_from( T _this_, FieldInfo[] fields, IDictionary<string,object> obj ) {
foreach ( var fld in fields ) {
var v = find( obj, fld.Name );
if ( v != null ) {
var mobj = call_deserialize( fld.FieldType, v );
fld.SetValue( _this_, mobj );
}
}
}
private void set_properties_from( T _this_, PropertyInfo[] properties, IDictionary<string,object> obj ) {
foreach ( var prop in properties ) {
var v = find( obj, prop.Name );
if ( v != null ) {
var mobj = call_deserialize( prop.PropertyType, v );
prop.SetValue( _this_, mobj, null );
}
}
}
private object find( IDictionary<string,object> obj, string name ) {
foreach ( var kv in obj )
if ( string.Compare( kv.Key, name, true ) == 0 )
return kv.Value;
return null;
}
private object call_deserialize( Type des_type, object value ) {
var gtype = typeof(dynamic_data_serializer<>);
Type desz_type = gtype.MakeGenericType( new[]{ des_type } );
object desz = Activator.CreateInstance( desz_type );
var method_type = desz_type.GetMethod( "create" );
return method_type.Invoke( desz, new[]{ value } );
}
}
}
Run Code Online (Sandbox Code Playgroud)
DataContractJsonSerializer 太慢,但您正在使用反射?如果您必须反序列化大量对象,我建议使用编译的 lambda 而不是反射。lambda 只能设置属性,不能设置字段(至少在 .Net 3.5 中),因此您可能必须调整使用它的类,但这是值得的,因为它的速度快了 1000 倍。
下面是一个函数,它创建一个属性设置器,给定类型和PropertyInfo
要设置的属性:
static Action<object, TValue> MakeSetter<TValue>(Type tclass, PropertyInfo propInfo)
{
var t = lambda.Expression.Parameter(typeof(object), "t");
var v = lambda.Expression.Parameter(typeof(TValue), "v");
// return (t, v) => ((tclass)t).prop = (tproperty)v
return (Action<object, TValue>)
lambda.Expression.Lambda(
lambda.Expression.Call(
lambda.Expression.Convert(t, tclass),
propInfo.GetSetMethod(),
lambda.Expression.Convert(v, propInfo.PropertyType)),
t,
v)
.Compile();
}
Run Code Online (Sandbox Code Playgroud)
您将为每个类都有一个 setter 字典,每当您必须设置类的属性时,您都会在字典中查找该属性的 setter 并使用要分配的值来调用它,如下所示:setters[propName](_this_, value);
归档时间: |
|
查看次数: |
6116 次 |
最近记录: |