资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 面试经验 > 面试问答

使用动态发出的POCO进行快速序列化和反序列化

面试问答 更新时间: 发布时间: 计算机考试归档 最新发布

使用动态发出的POCO进行快速序列化和反序列化

从评论和聊天看来,其中的关键部分仍然是创建动态类型。好的,这是一个完整的示例,显示了一个完全可序列化的(通过任何常见的序列化程序)类型。您当然可以在类型中添加更多内容-
可能是索引器,以按数字或按名称

INotifyPropertyChanged
等获取属性。

另外-关键点:您 必须 缓存并重新使用生成的

Type
实例。不要 守再生这个东西......你会出血内存。

using Newtonsoft.Json;using ProtoBuf;using System;using System.IO;using System.Reflection;using System.Reflection.Emit;using System.Runtime.Serialization;using System.Runtime.Serialization.Formatters.Binary;using System.Text;using System.Xml.Serialization;public interface IBasicRecord{    object this[int field] { get; set; }}class Program{    static void Main()    {        object o = 1;        int foo = (int)o;        string[] names = { "Id", "Name", "Size", "When" };        Type[] types = { typeof(int), typeof(string), typeof(float), typeof(DateTime?) };        var asm = AppDomain.CurrentDomain.DefineDynamicAssembly( new AssemblyName("DynamicStuff"), AssemblyBuilderAccess.Run);        var module = asm.DefineDynamicModule("DynamicStuff");        var tb = module.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Serializable);        tb.SetCustomAttribute(new CustomAttributeBuilder( typeof(DataContractAttribute).GetConstructor(Type.EmptyTypes), new object[0]));        tb.AddInterfaceImplementation(typeof(IBasicRecord));        FieldBuilder[] fields = new FieldBuilder[names.Length];        var dataMemberCtor = typeof(DataMemberAttribute).GetConstructor(Type.EmptyTypes);        var dataMemberProps = new[] { typeof(DataMemberAttribute).GetProperty("Order") };        for (int i = 0; i < fields.Length; i++)        { var field = fields[i] = tb.DefineField("_" + names[i],     types[i], FieldAttributes.Private); var prop = tb.DefineProperty(names[i], PropertyAttributes.None,     types[i], Type.EmptyTypes); var getter = tb.DefineMethod("get_" + names[i],     MethodAttributes.Public | MethodAttributes.HideBySig, types[i], Type.EmptyTypes); prop.SetGetMethod(getter); var il = getter.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Ldfld, field); // .Foo il.Emit(OpCodes.Ret); // return var setter = tb.DefineMethod("set_" + names[i],     MethodAttributes.Public | MethodAttributes.HideBySig, typeof(void), new Type[] { types[i] }); prop.SetSetMethod(setter); il = setter.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Ldarg_1); // value il.Emit(OpCodes.Stfld, field); // .Foo = il.Emit(OpCodes.Ret); prop.SetCustomAttribute(new CustomAttributeBuilder(     dataMemberCtor, new object[0],     dataMemberProps, new object[1] { i + 1 }));        }        foreach (var prop in typeof(IBasicRecord).GetProperties())        { var accessor = prop.GetGetMethod(); if (accessor != null) {     var args = accessor.GetParameters();     var argTypes = Array.ConvertAll(args, a => a.ParameterType);     var method = tb.DefineMethod(accessor.Name,         accessor.Attributes & ~MethodAttributes.Abstract,         accessor.CallingConvention, accessor.ReturnType, argTypes);     tb.DefineMethodOverride(method, accessor);     var il = method.GetILGenerator();     if (args.Length == 1 && argTypes[0] == typeof(int))     {         var branches = new Label[fields.Length];         for (int i = 0; i < fields.Length; i++)         {  branches[i] = il.DefineLabel();         }         il.Emit(OpCodes.Ldarg_1); // key         il.Emit(OpCodes.Switch, branches); // switch         // default:         il.ThrowException(typeof(ArgumentOutOfRangeException));         for (int i = 0; i < fields.Length; i++)         {  il.MarkLabel(branches[i]);  il.Emit(OpCodes.Ldarg_0); // this  il.Emit(OpCodes.Ldfld, fields[i]); // .Foo  if (types[i].IsValueType)  {      il.Emit(OpCodes.Box, types[i]); // (object)  }  il.Emit(OpCodes.Ret); // return         }     }     else     {         il.ThrowException(typeof(NotImplementedException));     } } accessor = prop.GetSetMethod(); if (accessor != null) {     var args = accessor.GetParameters();     var argTypes = Array.ConvertAll(args, a => a.ParameterType);     var method = tb.DefineMethod(accessor.Name,         accessor.Attributes & ~MethodAttributes.Abstract,         accessor.CallingConvention, accessor.ReturnType, argTypes);     tb.DefineMethodOverride(method, accessor);     var il = method.GetILGenerator();     if (args.Length == 2 && argTypes[0] == typeof(int) && argTypes[1] == typeof(object))     {         var branches = new Label[fields.Length];         for (int i = 0; i < fields.Length; i++)         {  branches[i] = il.DefineLabel();         }         il.Emit(OpCodes.Ldarg_1); // key         il.Emit(OpCodes.Switch, branches); // switch         // default:         il.ThrowException(typeof(ArgumentOutOfRangeException));         for (int i = 0; i < fields.Length; i++)         {  il.MarkLabel(branches[i]);  il.Emit(OpCodes.Ldarg_0); // this  il.Emit(OpCodes.Ldarg_2); // value  il.Emit(types[i].IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, types[i]); // (SomeType)  il.Emit(OpCodes.Stfld, fields[i]); // .Foo =  il.Emit(OpCodes.Ret); // return         }     }     else     {         il.ThrowException(typeof(NotImplementedException));     } }        }        var type = tb.CreateType();        var obj = Activator.CreateInstance(type);        // we'll use the index (via a known interface) to set the values        IBasicRecord rec = (IBasicRecord)obj;        rec[0] = 123;        rec[1] = "abc";        rec[2] = 12F;        rec[3] = DateTime.Now;        for (int i = 0; i < 4; i++)        { Console.WriteLine("{0} = {1}", i, rec[i]);        }        using (var ms = new MemoryStream())        { var ser = new XmlSerializer(type); ser.Serialize(ms, obj); Console.WriteLine("XmlSerializer: {0} bytes", ms.Length);        }        using (var ms = new MemoryStream())        { using (var writer = new StreamWriter(ms, Encoding.UTF8, 1024, true)) {     var ser = new JsonSerializer();     ser.Serialize(writer, obj); } Console.WriteLine("Json.NET: {0} bytes", ms.Length);        }        using (var ms = new MemoryStream())        { var ser = new DataContractSerializer(type); ser.WriteObject(ms, obj); Console.WriteLine("DataContractSerializer: {0} bytes", ms.Length);        }        using (var ms = new MemoryStream())        { Serializer.NonGeneric.Serialize(ms, obj); Console.WriteLine("protobuf-net: {0} bytes", ms.Length);        }        using (var ms = new MemoryStream())        { // note: NEVER do this unless you have a custom Binder; your // assembly WILL NOT deserialize in the next AppDomain (i.e. // the next time you load your app, you won't be able to load) // - shown only for illustration var bf = new BinaryFormatter(); bf.Serialize(ms, obj); Console.WriteLine("BinaryFormatter: {0} bytes", ms.Length);        }    }}

输出:

XmlSerializer: 246 bytesJson.NET: 81 bytesDataContractSerializer: 207 bytesprotobuf-net: 25 bytesBinaryFormatter: 182 bytes


转载请注明:文章转载自 http://www.konglu.com/
本文地址:http://www.konglu.com/it/376919.html
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【使用动态发出的POCO进行快速序列化和反序列化】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2