我正在使用这样的代码在运行时定义protobuf-net模式。我在收到错误:
CustomAttributeBuilder contractMem = new CustomAttributeBuilder(
contractMemInfoCon, new object[] { index });
as“Value not not null”。请帮我解决这个问题。
AssemblyName oAssemblyName = new AssemblyName();
oAssemblyName.Name = "TEST";
AssemblyBuilder oAssmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly("Test", AssemblyBuilderAccess.Run);
ModuleBuilder oModule = oAssmBuilder.DefineDynamicModule("TestModule.Module");
TypeBuilder oTypeBuilder = oModule.DefineType("TestType", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Serializable);
ConstructorBuilder constructor = oTypeBuilder.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
//For Defining protocontract
ConstructorInfo contractInfoCon = typeof(ProtoBuf.ProtoContractAttribute).GetConstructor(new Type[0]);
CustomAttributeBuilder cab = new CustomAttributeBuilder(contractInfoCon, new object[0]);
oTypeBuilder.SetCustomAttribute(cab);
string sDataType = "", sPropertyName = "";
int index = 0;
//oFields contains SP columns
foreach (Types.Field oField in oFields)
{
sPropertyName = oField.ID;
sDataType = oField.DataType;
index = index + 1;
FieldBuilder field = oTypeBuilder.DefineField(sPropertyName, oField.DataType, FieldAttributes.Public);
PropertyBuilder property =
oTypeBuilder.DefineProperty("_" + sPropertyName,
System.Reflection.PropertyAttributes.None,
oField.DataType,
new Type[] { oField.DataType });
MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig;
MethodBuilder currGetPropMthdBldr =
oTypeBuilder.DefineMethod("get_value",
GetSetAttr,
oField.DataType,
Type.EmptyTypes);
ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator();
currGetIL.Emit(OpCodes.Ldarg_0);
currGetIL.Emit(OpCodes.Ldfld, field);
currGetIL.Emit(OpCodes.Ret);
MethodBuilder currSetPropMthdBldr =
oTypeBuilder.DefineMethod("set_value",
GetSetAttr,
null,
new Type[] { oField.DataType });
ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ret);
property.SetGetMethod(currGetPropMthdBldr);
property.SetSetMethod(currSetPropMthdBldr);
ConstructorInfo contractMemInfoCon = typeof(ProtoBuf.ProtoMemberAttribute).GetConstructor(new [] { oField.DataType });
CustomAttributeBuilder contractMem = new CustomAttributeBuilder(contractMemInfoCon, new object[] { index });
property.SetCustomAttribute(contractMem);
}
答案 0 :(得分:1)
最终,问题来自:
ConstructorInfo contractMemInfoCon = typeof(ProtoBuf.ProtoMemberAttribute).GetConstructor(
new [] { oField.DataType });
这仅在oField.DataType
为int
时才有效,因为唯一的单参数ProtoContractAttribute
构造函数是int tag
的构造函数。对于任何其他oField.DataType
,此GetConstructor
来电将返回null
。立即解决的问题是每次使用typeof(int)
,而不是oField.DataType
。
但是,坦率地说,我不认为元编程是您在这种情况下使用的正确方法(尽管没有完整的例子很难说)。如果已经拥有对象模型,则可以使用RuntimeTypeModel
/ MetaType
/ ValueMember
API配置许多内容。我不知道这对你的具体情况有多好。
如果您特别关注序列化DataSet
,那么"对"方法可能取决于它是否是"打字"数据集,与非类型数据集。坦率地说,第一个我想说的是:
停止使用数据集
但我承认有一些(有限)场景,它们真正有用。它们不应该是您的默认数据访问技术。如果 使用数据集(DataSet
),请注意已经 内置的优化序列化格式 - 它只是默认情况下没有启用。如果您使用内置的.NET序列化测试DataSet
并发现它不满意,请尝试设置:
yourDataSet.RemotingFormat = SerializationFormat.Binary;
重新运行测试。这比默认的xml格式更有效 ,并且可能足以避免说服DataSet
与其他序列化程序很好地协作。