【发布时间】:2010-08-19 20:43:14
【问题描述】:
在运行时,我生成一个动态程序集,其中包含我的应用程序的数据模型。每个类都用DataContractAttribute 注释,每个属性都用DataMemberAttribute 注释。现在,如果我尝试序列化一个对象,生成的 XML 只包含根节点,但没有属性。但是,如果我在代码中定义完全相同的类 - 那么它工作正常。
到目前为止,我正在使用“用户”对象进行测试。这是“静态”实现:
[DataContract]
private class NonDynamicUser
{
[DataMember]
public Guid Id { get; set; }
[DataMember]
public String Username { get; set; }
[DataMember]
public String Password { get; set; }
}
这里是“动态”的:
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.RunAndCollect);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");
TypeBuilder userTypeBuilder = moduleBuilder.DefineType(assemblyName + "." + "User", TypeAttributes.Public);
Type attrType = typeof(DataContractAttribute);
userTypeBuilder.SetCustomAttribute(new CustomAttributeBuilder(attrType.GetConstructor(Type.EmptyTypes), new object[] { }));
CreateFieldForType(userTypeBuilder, typeof(Guid), "Id");
CreateFieldForType(userTypeBuilder, typeof(String), "Username");
CreateFieldForType(userTypeBuilder, typeof(String), "Password");
Type userType = userTypeBuilder.CreateType();
void CreateFieldForType(TypeBuilder typeBuilder, Type fieldType, String fieldName) 方法基本上是创建一个私有字段,然后是一个带有公共 getter 和 setter 的公共属性(用 DataMemberAttribute 注释)。
我通过反射再次创建要序列化的实例,这适用于“动态”对象以及“静态”对象:
object reflectedUser = Activator.CreateInstance(userType);
//object reflectedUser = Activator.CreateInstance(typeof(NonDynamicUser));
reflectedUser.GetType().GetProperty("Id").SetValue(reflectedUser, Guid.NewGuid(), null);
reflectedUser.GetType().GetProperty("Username").SetValue(reflectedUser, "s7orm", null);
reflectedUser.GetType().GetProperty("Password").SetValue(reflectedUser, "s7orm", null);
这就是我序列化对象的方式(直截了当的东西):
DataContractSerializer ser = new DataContractSerializer(reflectedUser.GetType());
ser.WriteObject(writer, reflectedUser);
这会产生不同的输出,具体取决于使用的是动态用户类还是静态用户类...
你知道我做错了什么吗?
更新:
这是CreateFieldForType方法的代码:
private static void CreateFieldForType(TypeBuilder typeBuilder, Type fieldType, String fieldName)
{
Type attrType = typeof(DataMemberAttribute);
CustomAttributeBuilder attr = new CustomAttributeBuilder(attrType.GetConstructor(Type.EmptyTypes), new object[] { });
FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + fieldName.ToLowerInvariant(), fieldType, FieldAttributes.Private);
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(fieldName, PropertyAttributes.HasDefault, fieldType, null);
propertyBuilder.SetCustomAttribute(attr);
MethodAttributes getterAndSetterAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual;
MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_" + propertyBuilder.Name, getterAndSetterAttributes, fieldType, Type.EmptyTypes);
ILGenerator getMethodILGenerator = getMethodBuilder.GetILGenerator();
getMethodILGenerator.Emit(OpCodes.Ldarg_0);
getMethodILGenerator.Emit(OpCodes.Ldfld, fieldBuilder);
getMethodILGenerator.Emit(OpCodes.Ret);
MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_" + propertyBuilder.Name, getterAndSetterAttributes, null, new Type[] { fieldType });
ILGenerator setMethodILGenerator = setMethodBuilder.GetILGenerator();
setMethodILGenerator.Emit(OpCodes.Ldarg_0);
setMethodILGenerator.Emit(OpCodes.Ldarg_1);
setMethodILGenerator.Emit(OpCodes.Stfld, fieldBuilder);
setMethodILGenerator.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getMethodBuilder);
propertyBuilder.SetSetMethod(setMethodBuilder);
}
【问题讨论】:
-
您可以使用 .NET 反射器查看您生成的代码与编译器为您的静态版本生成的代码之间的差异。
-
我已经尝试过了,但是当我用红色门的反射器打开动态程序集(当然首先保存程序集)时,它没有显示任何类。一些奇怪的事情正在发生......
-
为方便起见,您可以粘贴您的 CreateFieldForType 代码吗?
-
没问题,我更新了帖子。
标签: c# serialization