我目前正在将SQL表行序列化为二进制格式,以进行有效存储。我将二进制数据序列化/反序列化为List<object>
每行。我正在尝试将其升级为使用POCO,该POCO将html" target="_blank">动态生成(发射),每列一个字段。
我一直在网上搜索数小时,偶然发现了EF,T4,ExpandoObject之类的ORM
/框架,但所有这些要么使用动态对象(可以动态添加/删除属性),要么在编译之前简单地生成POCO。我不能使用模板,因为在编译时表的模式是未知的,并且使用动态对象会太过费力(并且很慢),因为我知道确切的属性集和类型。我需要为每个表生成一个POCO,其中Fields对应于列,并相应地设置数据类型(INT->
int,TEXT->字符串)。
生成POCO之后,我将继续使用发出的CIL获取/设置属性,就像PetaPoco对静态编译的POCO所做的一样。我希望所有这些技巧都比使用无类型列表更快,并为我提供高强度POCO,这些POCO具有强类型并且可以通过CLR加速。我是否正确地假设了这一点?您可以在运行时开始生成POCO吗?并且使用POCO会比使用POCO更快或更有效List<object>
吗?基本上,值得为此烦恼吗?我已经知道如何使用发出的CIL加速获取/设置字段。
从评论和聊天看来,其中的关键部分仍然是创建动态类型。好的,这是一个完整的示例,显示了一个完全可序列化的(通过任何常见的序列化程序)类型。您当然可以在类型中添加更多内容-
可能是索引器,以按数字或按名称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 bytes
Json.NET: 81 bytes
DataContractSerializer: 207 bytes
protobuf-net: 25 bytes
BinaryFormatter: 182 bytes
本文向大家介绍C#使用Json.Net进行序列化和反序列化及定制化,包括了C#使用Json.Net进行序列化和反序列化及定制化的使用技巧和注意事项,需要的朋友参考一下 序列化(Serialize)是将对象转换成字节流,并将其用于存储或传输的过程,主要用途是保存对象的状态,以便在需要时重新创建该对象;反序列化(Deserialize)则是将上面的字节流转换为相应对象的过程;在.Net阵营中,Json
本文向大家介绍Python使用pickle进行序列化和反序列化的示例代码,包括了Python使用pickle进行序列化和反序列化的示例代码的使用技巧和注意事项,需要的朋友参考一下 一、说明 早上看到Python使用pickle进行序列化和反序列化,然后发现面临的一个获取不到返回值的框架,似乎可以通过在框架中先序列化,然后在外部进行反序列化的方法来实现。就研究了一下pickle库的具体使用。 本身也
I'va是一个OID接口,可以由许多具体类型实现: 现在我有一个具有两个字段的对象,一个使用抽象接口类型(OID)定义,另一个使用具体类型(MyOID)定义 我想使用jackson以不同的方式序列化/反序列化字段,无论它们是使用抽象接口类型还是具体类型定义的: 注意,被序列化,包括类型信息(多态序列化),而被序列化为文本 为此,我将OID接口注释为: 并为每个具体类型分配了类型id: 最后,对容器
问题内容: 我是C ++的新手。使用序列化和反序列化类型数据的最简单方法是什么。我发现了一些使用示例,但它们对我来说是晦涩的。 问题答案: 请注意,将键解释为路径,例如,将对“ ab” =“ z”放置将创建{“ a”:{“ b”:“ z”}} JSON,而不是{“ ab”:“ z”} 。否则,使用是微不足道的。这是一个小例子。
我有一个字段,它通过类序列化为ISO-8601格式。 当我收到以下JSON时, 通过将jackson-datatype-jsr310模块包含到项目中,并使用和解决了这个问题。
问题内容: 我正在从如下所示的Web API接收JSON数据: 我将此数据反序列化为以下类型的对象: 稍后在我的应用程序中,我想再次将ErrorDetails对象序列化为JSON,但使用属性名称代替。因此结果将如下所示: 有什么简单的方法可以使用Json.Net完成此操作?也许使用自定义解析器和一些属性,例如: 但是解析器不会告诉我何时进行序列化或反序列化。 问题答案: 您可以使用,Contrac