Я столкнулся с проблемой и подумал, есть ли простой способ ее решения.
Здесь у меня есть шаблон XML, определяющий некоторые свойства и их значения.
<Properties>
<Property name="ID">10000</Property>
<Property name="Name">
<SubProperty name="FirstName">Foo</SubProperty>
<SubProperty name="LastName">Bar</SubProperty >
</Property>
</Properties>
Все, что нужно для извлечения свойств / вложенных свойств, определенных в шаблоне, для создания нового XML-файла со всеми присоединенными значениями, что-то вроде
<Items>
<ID>10000</ID>
<Name>
<FirstName>Foo</FirstName>
<LastName>Bar</LastName>
</Name>
</Items>
Поскольку я не знаю содержимого шаблона во время разработки, я попытался загрузить его и создал класс List с использованием LINQ, но не могу получить приведенный выше результат при его непосредственной сериализации. Поэтому вместо создания класса List я создал динамический объект, используя Reflection.Emit, а затем сериализовал объект в XML.
private static readonly XDocument doc = XDocument.Load("Template.xml");
static void Main(string[] args) {
var newType = CreateDynamicType();
var newObject = Activator.CreateInstance(newType);
var properties = newType.GetProperties();
foreach (var property in properties) {
// assign values
}
SerializeToXml(newObject);
}
private static Type CreateDynamicType() {
AssemblyName assemblyName = new AssemblyName() { Name = "DynamicTypeAdapter" };
AssemblyBuilder assembly =
Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder module =
assembly.DefineDynamicModule(assembly.GetName().Name, false);
TypeBuilder type = module.DefineType("Items", TypeAttributes.Public | TypeAttributes.Class);
foreach (var p in doc.Descendants("Property")) {
string pName = p.Attribute("name").Value;
TypeBuilder subType = module.DefineType(pName, TypeAttributes.Public | TypeAttributes.Class);
foreach (var sp in p.Descendants("SubProperty")) {
CreateDynamicProperty(subType, sp.Attribute("name").Value, typeof(string));
}
var propertyType = subType.CreateType();
CreateDynamicProperty(type, pName, propertyType);
}
return type.CreateType();
}
private static void CreateDynamicProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType) {
PropertyBuilder property = typeBuilder.DefineProperty(propertyName,
PropertyAttributes.None, propertyType, new Type[] { typeof(string) });
FieldBuilder field = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
MethodAttributes GetSetAttributes = MethodAttributes.Public | MethodAttributes.HideBySig;
MethodBuilder getMethod =
typeBuilder.DefineMethod("get_value", GetSetAttributes, propertyType, Type.EmptyTypes);
ILGenerator getIL = getMethod.GetILGenerator();
getIL.Emit(OpCodes.Ldarg_0);
getIL.Emit(OpCodes.Ldfld, field);
getIL.Emit(OpCodes.Ret);
MethodBuilder setMethod =
typeBuilder.DefineMethod("set_value", GetSetAttributes, null, new Type[] { typeof(string) });
ILGenerator setIL = setMethod.GetILGenerator();
setIL.Emit(OpCodes.Ldarg_0);
setIL.Emit(OpCodes.Ldarg_1);
setIL.Emit(OpCodes.Stfld, field);
setIL.Emit(OpCodes.Ret);
property.SetGetMethod(getMethod);
property.SetSetMethod(setMethod);
}
Работает нормально, но есть ли простой способ сделать это?
Любой комментарий приветствуется. Спасибо