public static Type CreateClassProxy(Type serviceType, Type implementType) { if (null == serviceType) { throw new ArgumentNullException(nameof(serviceType)); } if (null == implementType) { implementType = serviceType; } if (serviceType.IsSealed || implementType.IsSealed) { throw new InvalidOperationException("the class type is sealed"); } // var proxyTypeName = _proxyTypeNameResolver(serviceType, implementType); if (_proxyTypes.TryGetValue(proxyTypeName, out var proxyType)) { return(proxyType); } lock (_typeLock) { if (_proxyTypes.TryGetValue(proxyTypeName, out proxyType)) { return(proxyType); } var typeBuilder = _moduleBuilder.DefineType(proxyTypeName, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class, implementType, Type.EmptyTypes); GenericParameterUtils.DefineGenericParameter(implementType, typeBuilder); var targetField = typeBuilder.DefineField(TargetFieldName, implementType, FieldAttributes.Private); // constructors var constructors = implementType.GetConstructors(); if (constructors.Length > 0) { foreach (var constructor in constructors) { var constructorTypes = constructor.GetParameters().Select(o => o.ParameterType).ToArray(); var constructorBuilder = typeBuilder.DefineConstructor( constructor.Attributes, constructor.CallingConvention, constructorTypes); foreach (var customAttribute in constructor.CustomAttributes) { constructorBuilder.SetCustomAttribute(DefineCustomAttribute(customAttribute)); } var il = constructorBuilder.GetILGenerator(); il.EmitThis(); for (var i = 0; i < constructorTypes.Length; i++) { il.Emit(OpCodes.Ldarg, i + 1); } il.Call(constructor); il.Emit(OpCodes.Nop); il.EmitThis(); il.EmitThis(); il.Emit(OpCodes.Stfld, targetField); il.Emit(OpCodes.Ret); } } else { var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Type.EmptyTypes); var il = constructorBuilder.GetILGenerator(); il.EmitThis(); il.EmitThis(); il.Emit(OpCodes.Stfld, targetField); il.Emit(OpCodes.Ret); } // properties var propertyMethods = new HashSet <string>(); foreach (var property in serviceType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { if (property.IsVisibleAndVirtual()) { var propertyBuilder = typeBuilder.DefineProperty(property.Name, property.Attributes, property.PropertyType, Type.EmptyTypes); //inherit targetMethod's attribute foreach (var customAttributeData in property.CustomAttributes) { propertyBuilder.SetCustomAttribute(DefineCustomAttribute(customAttributeData)); } if (property.CanRead) { propertyMethods.Add(property.GetMethod.Name); var method = MethodUtils.DefineClassMethod(typeBuilder, property.GetMethod, targetField); propertyBuilder.SetGetMethod(method); } if (property.CanWrite) { propertyMethods.Add(property.SetMethod.Name); var method = MethodUtils.DefineClassMethod(typeBuilder, property.SetMethod, targetField); propertyBuilder.SetSetMethod(method); } } } // methods var methods = serviceType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .Where(m => m.IsVirtual && !m.IsFinal && m.IsVisible() && !propertyMethods.Contains(m.Name) && !_ignoredMethods.Contains(m.Name)) .ToArray(); foreach (var method in methods) { MethodUtils.DefineClassMethod(typeBuilder, method, targetField); } proxyType = typeBuilder.CreateType(); _proxyTypes[proxyTypeName] = proxyType; return(proxyType); } }