diff --git a/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache b/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache index 8950e52..9e86bbc 100644 --- a/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache +++ b/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -fe8032ac49bedc0ec84767ee0419b2fc618b5766 +e6d14b54c463a8096220ac67f9a339de12a3fb4a diff --git a/ZeroLevel/Services/Reflection/DTOTypeBuilder.cs b/ZeroLevel/Services/Reflection/DTOTypeBuilder.cs new file mode 100644 index 0000000..2d0a8cd --- /dev/null +++ b/ZeroLevel/Services/Reflection/DTOTypeBuilder.cs @@ -0,0 +1,151 @@ +using System; +using System.ComponentModel; +using System.Reflection; +using System.Reflection.Emit; +using System.Runtime.Serialization; +using System.Threading; + +namespace ZeroLevel.Services.Reflection +{ + /// + /// Конструктор простейших типов, без методов + /// + public sealed class DTOTypeBuilder + { + #region Fields + private readonly TypeBuilder _typeBuilder; + #endregion + + /// + /// Конструктор + /// + /// Название создаваемого типа + public DTOTypeBuilder(string typeName) + { + var newAssemblyName = new AssemblyName(Guid.NewGuid().ToString()); + var assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(newAssemblyName, AssemblyBuilderAccess.Run); + var moduleBuilder = assemblyBuilder.DefineDynamicModule(newAssemblyName.Name); + _typeBuilder = moduleBuilder.DefineType(typeName, + TypeAttributes.Public | + TypeAttributes.Class | + TypeAttributes.AutoClass | + TypeAttributes.AnsiClass | + TypeAttributes.BeforeFieldInit | TypeAttributes.Serializable | + TypeAttributes.AutoLayout, typeof(object)); + + var a_ctor = typeof(DataContractAttribute).GetConstructor(new Type[] { }); + var a_builder = new CustomAttributeBuilder(a_ctor, new object[] { }); + _typeBuilder.SetCustomAttribute(a_builder); + } + + public void AppendField(string name) + { + _typeBuilder.DefineField(name, typeof(T), FieldAttributes.Public); + } + + public void AppendField(string name, T defaultValue) + { + var builder = _typeBuilder.DefineField(name, typeof(T), FieldAttributes.Public | FieldAttributes.HasDefault); + builder.SetConstant(defaultValue); + } + + public void AppendProperty(string name) + { + CreateProperty(name, _typeBuilder, null); + } + + public void AppendProperty(string name, T defaultValue) + { + CreateProperty(name, _typeBuilder, null).SetConstant(defaultValue); + } + + public void AppendProperty(string name, string description) + { + CreateProperty(name, _typeBuilder, description); + } + + public void AppendProperty(string name, string description, T defaultValue) + { + CreateProperty(name, _typeBuilder, description).SetConstant(defaultValue); + } + + public void AppendProperty(Type propertyType, string name) + { + CreateProperty(propertyType, name, _typeBuilder, null); + } + + public void AppendProperty(Type propertyType, string name, object defaultValue) + { + CreateProperty(propertyType, name, _typeBuilder, null).SetConstant(defaultValue); + } + + public void AppendProperty(Type propertyType, string name, string description) + { + CreateProperty(propertyType, name, _typeBuilder, description); + } + + public void AppendProperty(Type propertyType, string name, string description, object defaultValue) + { + CreateProperty(propertyType, name, _typeBuilder, description).SetConstant(defaultValue); + } + + private static FieldBuilder CreateProperty(string name, + TypeBuilder typeBuilder, + string description) + { + return CreateProperty(typeof(T), name, typeBuilder, description); + } + + private static FieldBuilder CreateProperty(Type propertyType, string name, + TypeBuilder typeBuilder, + string description) + { + var backingFieldBuilder = typeBuilder.DefineField("f__" + name.ToLowerInvariant(), propertyType, FieldAttributes.Private); + var propertyBuilder = typeBuilder.DefineProperty(name, PropertyAttributes.HasDefault, + propertyType, new Type[] { propertyType }); + // Build setter + var getterMethodBuilder = typeBuilder.DefineMethod("get_" + name, + MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, + propertyType, Type.EmptyTypes); + var getterIl = getterMethodBuilder.GetILGenerator(); + getterIl.Emit(OpCodes.Ldarg_0); + getterIl.Emit(OpCodes.Ldfld, backingFieldBuilder); + getterIl.Emit(OpCodes.Ret); + // Build setter + var setterMethodBuilder = typeBuilder.DefineMethod("set_" + name, + MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, + null, new[] { propertyType }); + var setterIl = setterMethodBuilder.GetILGenerator(); + setterIl.Emit(OpCodes.Ldarg_0); + setterIl.Emit(OpCodes.Ldarg_1); + setterIl.Emit(OpCodes.Stfld, backingFieldBuilder); + setterIl.Emit(OpCodes.Ret); + propertyBuilder.SetGetMethod(getterMethodBuilder); + propertyBuilder.SetSetMethod(setterMethodBuilder); + // Set description attribute + if (false == string.IsNullOrWhiteSpace(description)) + { + var ctorParams = new[] { typeof(string) }; + var classCtorInfo = typeof(DescriptionAttribute).GetConstructor(ctorParams); + var myCABuilder = new CustomAttributeBuilder(classCtorInfo, new object[] { description }); + propertyBuilder.SetCustomAttribute(myCABuilder); + } + var a_ctor = typeof(DataMemberAttribute).GetConstructor(new Type[] { }); + var a_builder = new CustomAttributeBuilder(a_ctor, new object[] { }); + propertyBuilder.SetCustomAttribute(a_builder); + return backingFieldBuilder; + } + + /// + /// Собирает конечный тип + /// + /// Готовый тип + public Type Complete() + { + // Сборка типа + var type = _typeBuilder.CreateType(); + // Результат + return type; + } + } +} diff --git a/ZeroLevel/ZeroLevel.csproj b/ZeroLevel/ZeroLevel.csproj index 85aee82..db9b06e 100644 --- a/ZeroLevel/ZeroLevel.csproj +++ b/ZeroLevel/ZeroLevel.csproj @@ -290,6 +290,7 @@ + diff --git a/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache b/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache index 91b6aaf..b62c01d 100644 --- a/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache +++ b/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -f165fe7fc045ddedd4b08504422209fd88e56cc6 +35db55177c262262ace2e47d49fa51ff7b48a736