public static Type CreateInterfaceProxy(Type interfaceType) { if (null == interfaceType) { throw new ArgumentNullException(nameof(interfaceType)); } if (!interfaceType.IsInterface) { throw new InvalidOperationException($"{interfaceType.FullName} is not an interface"); } var proxyTypeName = _proxyTypeNameResolver(interfaceType, null); 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.Class | TypeAttributes.Sealed, typeof(object), new[] { interfaceType }); GenericParameterUtils.DefineGenericParameter(interfaceType, typeBuilder); // define default constructor typeBuilder.DefineDefaultConstructor(MethodAttributes.Public); // properties var propertyMethods = new HashSet <string>(); var properties = interfaceType.GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (var property in properties) { var propertyBuilder = typeBuilder.DefineProperty(property.Name, property.Attributes, property.PropertyType, Type.EmptyTypes); var field = typeBuilder.DefineField($"_{property.Name}", property.PropertyType, FieldAttributes.Private); if (property.CanRead) { var methodBuilder = typeBuilder.DefineMethod(property.GetMethod.Name, InterfaceMethodAttributes, property.GetMethod.CallingConvention, property.GetMethod.ReturnType, property.GetMethod.GetParameters().Select(p => p.ParameterType).ToArray()); var ilGen = methodBuilder.GetILGenerator(); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldfld, field); ilGen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, property.GetMethod); propertyBuilder.SetGetMethod(methodBuilder); propertyMethods.Add(property.GetMethod.Name); } if (property.CanWrite) { var methodBuilder = typeBuilder.DefineMethod(property.SetMethod.Name, InterfaceMethodAttributes, property.SetMethod.CallingConvention, property.SetMethod.ReturnType, property.SetMethod.GetParameters().Select(p => p.ParameterType).ToArray()); var ilGen = methodBuilder.GetILGenerator(); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldarg_1); ilGen.Emit(OpCodes.Stfld, field); ilGen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, property.SetMethod); propertyBuilder.SetSetMethod(methodBuilder); propertyMethods.Add(property.SetMethod.Name); } foreach (var customAttributeData in property.CustomAttributes) { propertyBuilder.SetCustomAttribute(DefineCustomAttribute(customAttributeData)); } } // methods var methods = interfaceType.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (var method in methods.Where(x => !propertyMethods.Contains(x.Name) && !_ignoredMethods.Contains(x.Name))) { MethodUtils.DefineInterfaceMethod(typeBuilder, method, null); } foreach (var implementedInterface in interfaceType.GetImplementedInterfaces()) { properties = implementedInterface.GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (var property in properties) { var propertyBuilder = typeBuilder.DefineProperty(property.Name, property.Attributes, property.PropertyType, Type.EmptyTypes); var field = typeBuilder.DefineField($"_{property.Name}", property.PropertyType, FieldAttributes.Private); if (property.CanRead) { var methodBuilder = typeBuilder.DefineMethod(property.GetMethod.Name, InterfaceMethodAttributes, property.GetMethod.CallingConvention, property.GetMethod.ReturnType, property.GetMethod.GetParameters().Select(p => p.ParameterType).ToArray()); var ilGen = methodBuilder.GetILGenerator(); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldfld, field); ilGen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, property.GetMethod); propertyBuilder.SetGetMethod(methodBuilder); propertyMethods.Add(property.GetMethod.Name); } if (property.CanWrite) { var methodBuilder = typeBuilder.DefineMethod(property.SetMethod.Name, InterfaceMethodAttributes, property.SetMethod.CallingConvention, property.SetMethod.ReturnType, property.SetMethod.GetParameters().Select(p => p.ParameterType).ToArray()); var ilGen = methodBuilder.GetILGenerator(); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldarg_1); ilGen.Emit(OpCodes.Stfld, field); ilGen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, property.SetMethod); propertyBuilder.SetSetMethod(methodBuilder); propertyMethods.Add(property.SetMethod.Name); } foreach (var customAttributeData in property.CustomAttributes) { propertyBuilder.SetCustomAttribute(DefineCustomAttribute(customAttributeData)); } } methods = implementedInterface.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (var method in methods.Where(x => !propertyMethods.Contains(x.Name) && !_ignoredMethods.Contains(x.Name))) { MethodUtils.DefineInterfaceMethod(typeBuilder, method, null); } } proxyType = typeBuilder.CreateType(); _proxyTypes[proxyTypeName] = proxyType; return(proxyType); } }
public static Type CreateInterfaceProxy(Type interfaceType, Type implementType) { if (null == interfaceType) { throw new ArgumentNullException(nameof(interfaceType)); } if (!interfaceType.IsInterface) { throw new InvalidOperationException($"{interfaceType.FullName} is not an interface"); } if (null == implementType) { return(CreateInterfaceProxy(interfaceType)); } if (implementType.IsSealed) { throw new InvalidOperationException("the implementType is sealed"); } var proxyTypeName = _proxyTypeNameResolver(interfaceType, implementType); var type = _proxyTypes.GetOrAdd(proxyTypeName, name => { var typeBuilder = _moduleBuilder.DefineType(proxyTypeName, implementType.Attributes, implementType, new[] { interfaceType }); GenericParameterUtils.DefineGenericParameter(interfaceType, typeBuilder); var targetField = typeBuilder.DefineField(TargetFieldName, implementType, FieldAttributes.Private); // constructors foreach (var constructor in implementType.GetConstructors()) { 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.EmitThis(); il.EmitThis(); il.Emit(OpCodes.Stfld, targetField); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ret); } // properties var propertyMethods = new HashSet <string>(); var properties = interfaceType.GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (var property in properties) { var propertyBuilder = typeBuilder.DefineProperty(property.Name, property.Attributes, property.PropertyType, Type.EmptyTypes); if (property.CanRead) { var methodBuilder = MethodUtils.DefineInterfaceMethod(typeBuilder, property.GetMethod, targetField); typeBuilder.DefineMethodOverride(methodBuilder, property.GetMethod); propertyBuilder.SetGetMethod(methodBuilder); propertyMethods.Add(property.GetMethod.Name); } if (property.CanWrite) { var methodBuilder = MethodUtils.DefineInterfaceMethod(typeBuilder, property.SetMethod, targetField); typeBuilder.DefineMethodOverride(methodBuilder, property.SetMethod); propertyBuilder.SetSetMethod(methodBuilder); propertyMethods.Add(property.SetMethod.Name); } foreach (var customAttributeData in property.CustomAttributes) { propertyBuilder.SetCustomAttribute(DefineCustomAttribute(customAttributeData)); } } // var methods = interfaceType.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (var method in methods) { if (propertyMethods.Contains(method.Name) || _ignoredMethods.Contains(method.Name)) { continue; } MethodUtils.DefineInterfaceMethod(typeBuilder, method, targetField); } foreach (var implementedInterface in interfaceType.GetImplementedInterfaces()) { properties = implementedInterface.GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (var property in properties) { var propertyBuilder = typeBuilder.DefineProperty(property.Name, property.Attributes, property.PropertyType, Type.EmptyTypes); var field = typeBuilder.DefineField($"_{property.Name}", property.PropertyType, FieldAttributes.Private); if (property.CanRead) { var methodBuilder = typeBuilder.DefineMethod(property.GetMethod.Name, InterfaceMethodAttributes, property.GetMethod.CallingConvention, property.GetMethod.ReturnType, property.GetMethod.GetParameters().Select(p => p.ParameterType).ToArray()); var ilGen = methodBuilder.GetILGenerator(); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldfld, field); ilGen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, property.GetMethod); propertyBuilder.SetGetMethod(methodBuilder); propertyMethods.Add(property.GetMethod.Name); } if (property.CanWrite) { var methodBuilder = typeBuilder.DefineMethod(property.SetMethod.Name, InterfaceMethodAttributes, property.SetMethod.CallingConvention, property.SetMethod.ReturnType, property.SetMethod.GetParameters().Select(p => p.ParameterType).ToArray()); var ilGen = methodBuilder.GetILGenerator(); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldarg_1); ilGen.Emit(OpCodes.Stfld, field); ilGen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, property.SetMethod); propertyBuilder.SetSetMethod(methodBuilder); propertyMethods.Add(property.SetMethod.Name); } foreach (var customAttributeData in property.CustomAttributes) { propertyBuilder.SetCustomAttribute(DefineCustomAttribute(customAttributeData)); } } methods = implementedInterface.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (var method in methods.Where(x => !propertyMethods.Contains(x.Name) && !_ignoredMethods.Contains(x.Name))) { MethodUtils.DefineInterfaceMethod(typeBuilder, method, null); } } return(typeBuilder.CreateType()); }); return(type); }