Beispiel #1
0
        /// <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());
        }
Beispiel #2
0
        /// <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());
        }