/// <summary> /// 构造实体类 <paramref name="entityType"/> 的代理类。 /// </summary> /// <param name="entityType"></param> /// <param name="entityName"></param> /// <param name="assemblyBuilder"></param> /// <param name="injection"></param> /// <returns></returns> public static Type BuildType(Type entityType, string entityName, DynamicAssemblyBuilder assemblyBuilder = null, IInjectionProvider injection = null) { var typeBuilder = assemblyBuilder.DefineType(entityName ?? entityType.Name, baseType: entityType); typeBuilder.ImplementInterface(typeof(ICompiledEntity)); typeBuilder.SetCustomAttribute(() => new SerializableAttribute()); var properties = from s in entityType.GetProperties() let getMth = s.GetGetMethod() where getMth.IsVirtual && !getMth.IsFinal select s; foreach (var property in properties) { var propertyBuilder = typeBuilder.DefineProperty(property.Name, property.PropertyType); var get = property.GetGetMethod(); var set = property.GetSetMethod(); var isEnum = property.PropertyType.GetNonNullableType().IsEnum; var opType = isEnum ? typeof(Enum) : property.PropertyType; if (get != null) { var op_Explicit = typeof(PropertyValue).GetMethods().FirstOrDefault(s => s.Name == "op_Explicit" && s.ReturnType == opType); propertyBuilder.DefineGetMethod(ilCoding: code => { code.Emitter.DeclareLocal(get.ReturnType); code.Emitter .nop .ldarg_0 .ldtoken(entityType) .call(MthTypeGetTypeFromHandle) .ldstr(property.Name) .call(MthGetProperty) .call(MthGetValue) .Assert(op_Explicit != null, e1 => e1.call(op_Explicit), e1 => e1.call(MthPVGetValue).castclass(opType)) .Assert(isEnum, e1 => e1.unbox_any(property.PropertyType)) .stloc_0 .ldloc_0 .ret(); }); } if (set != null) { var op_Implicit = typeof(PropertyValue).GetMethods().FirstOrDefault(s => s.Name == "op_Implicit" && s.GetParameters()[0].ParameterType == opType); propertyBuilder.DefineSetMethod(ilCoding: code => { code.Emitter .nop .ldarg_0 .ldtoken(entityType) .call(MthTypeGetTypeFromHandle) .ldstr(property.Name) .call(MthGetProperty) .ldarg_1 .Assert(isEnum, e1 => e1.box(property.PropertyType)) .Assert(op_Implicit != null, e1 => e1.call(op_Implicit), e1 => e1.ldnull.call(MthPVNewValue)) .call(MthSetValue) .nop .ret(); }); } } var initMethod = typeBuilder.DefineMethod("InitializeValue", parameterTypes: new[] { typeof(IProperty), typeof(PropertyValue) }, ilCoding: code => { code.Emitter. ldarg_0.ldarg_1.ldarg_2. callvirt(MthInitValue).ret(); }); injection?.Inject(entityType, assemblyBuilder, typeBuilder); return(typeBuilder.CreateType()); }
/// <summary> /// 构造实体类 <paramref name="entityType"/> 的代理类。 /// </summary> /// <param name="entityType"></param> /// <param name="entityName"></param> /// <param name="assemblyBuilder"></param> /// <param name="injection"></param> /// <returns></returns> public static Type BuildType(Type entityType, string entityName, DynamicAssemblyBuilder assemblyBuilder = null, IInjectionProvider injection = null) { var typeBuilder = assemblyBuilder.DefineType(entityName ?? entityType.Name, baseType: entityType); typeBuilder.ImplementInterface(typeof(ICompiledEntity)); typeBuilder.SetCustomAttribute(() => new SerializableAttribute()); //重写构造器 foreach (var cons in entityType.GetConstructors(BindingFlags.Public | BindingFlags.Instance)) { var parameters = cons.GetParameters(); typeBuilder.DefineConstructor(parameters.Select(s => s.ParameterType).ToArray()).AppendCode(e => { e.ldarg_0.For(0, parameters.Length, (b, i) => b.ldarg(i + 1)) .call(cons).nop.ret(); }); } //重写属性 var properties = from s in entityType.GetProperties() let getMth = s.GetGetMethod() where getMth.IsVirtual && !getMth.IsFinal select s; foreach (var property in properties) { var propertyBuilder = typeBuilder.DefineProperty(property.Name, property.PropertyType); var get = property.GetGetMethod(); var set = property.GetSetMethod(); var isEnum = property.PropertyType.GetNonNullableType().IsEnum; var opType = isEnum ? typeof(Enum) : property.PropertyType; if (get != null) { var op_Explicit = ReflectionCache.GetMember("PropertyValue_Explicit", opType, "op_Explicit", (k, n) => typeof(PropertyValue).GetMethods().FirstOrDefault(s => s.Name == n && s.ReturnType == k)); propertyBuilder.DefineGetMethod(ilCoding: code => { code.Emitter.DeclareLocal(typeof(PropertyValue)); code.Emitter.DeclareLocal(get.ReturnType); code.Emitter .nop .ldarg_0 .ldtoken(entityType) .call(MethodCache.TypeGetTypeFromHandle) .ldstr(property.Name) .call(MethodCache.GetProperty) .call(MethodCache.GetValue) .Assert(op_Explicit != null, e1 => e1.call(op_Explicit), e1 => e1.call(MethodCache.PVGetValue.MakeGenericMethod(property.PropertyType))) .Assert(isEnum, e1 => e1.unbox_any(property.PropertyType)) .stloc_1 .ldloc_1 .ret(); }); } if (set != null) { var op_Implicit = ReflectionCache.GetMember("PropertyValue_Implicit", opType, "op_Implicit", (k, n) => typeof(PropertyValue).GetMethods().FirstOrDefault(s => s.Name == n && s.GetParameters()[0].ParameterType == k)); propertyBuilder.DefineSetMethod(ilCoding: code => { code.Emitter .nop .ldarg_0 .ldtoken(entityType) .call(MethodCache.TypeGetTypeFromHandle) .ldstr(property.Name) .call(MethodCache.GetProperty) .ldarg_1 .Assert(isEnum, e1 => e1.box(property.PropertyType)) .Assert(op_Implicit != null, e1 => e1.call(op_Implicit), e1 => e1.ldtoken(property.PropertyType).call(MethodCache.TypeGetTypeFromHandle).call(MethodCache.PVNewValue)) .call(MethodCache.SetValue) .nop .ret(); }); } } var initMethod = typeBuilder.DefineMethod("InitializeValue", parameterTypes: new[] { typeof(IProperty), typeof(PropertyValue) }, ilCoding: code => { code.Emitter. ldarg_0.ldarg_1.ldarg_2. callvirt(MethodCache.InitValue).ret(); }); injection?.Inject(new EntityInjectionContext { EntityType = entityType, AssemblyBuilder = assemblyBuilder, TypeBuilder = typeBuilder }); return(typeBuilder.CreateType()); }