コード例 #1
0
        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);
            }
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
            public static MethodBuilder DefineClassMethod(TypeBuilder typeBuilder, MethodInfo method, FieldBuilder targetField)
            {
                var methodParameterTypes = method.GetParameters()
                                           .Select(p => p.ParameterType)
                                           .ToArray();

                var methodAttributes = OverrideMethodAttributes;

                if (method.Attributes.HasFlag(MethodAttributes.Public))
                {
                    methodAttributes |= MethodAttributes.Public;
                }
                if (method.Attributes.HasFlag(MethodAttributes.Family))
                {
                    methodAttributes |= MethodAttributes.Family;
                }
                if (method.Attributes.HasFlag(MethodAttributes.FamORAssem))
                {
                    methodAttributes |= MethodAttributes.FamORAssem;
                }
                var methodBuilder = typeBuilder.DefineMethod(method.Name,
                                                             methodAttributes,
                                                             method.CallingConvention,
                                                             method.ReturnType,
                                                             methodParameterTypes
                                                             );

                GenericParameterUtils.DefineGenericParameter(method, methodBuilder);

                foreach (var customAttributeData in method.CustomAttributes)
                {
                    methodBuilder.SetCustomAttribute(DefineCustomAttribute(customAttributeData));
                }

                var il = methodBuilder.GetILGenerator();

                var localReturnValue   = il.DeclareReturnValue(method.ReturnType);
                var localCurrentMethod = il.DeclareLocal(typeof(MethodInfo));
                var localMethodBase    = il.DeclareLocal(typeof(MethodInfo));
                var localParameters    = il.DeclareLocal(typeof(object[]));

                // var currentMethod = MethodBase.GetCurrentMethod();
                il.Call(MethodInvokeHelper.GetCurrentMethod);
                il.EmitConvertToType(typeof(MethodBase), typeof(MethodInfo));
                il.Emit(OpCodes.Stloc, localCurrentMethod);

                var targetMethod = targetField?.FieldType.GetMethodBySignature(method);

                if (null != targetMethod)
                {
                    il.EmitMethod(methodBuilder.IsGenericMethod
                        ? targetMethod.MakeGenericMethod(methodBuilder.GetGenericArguments())
                        : targetMethod);
                }
                else
                {
                    il.EmitNull();
                }
                il.Emit(OpCodes.Stloc, localMethodBase);

                // var parameters = new[] {a, b, c};
                il.Emit(OpCodes.Ldc_I4, methodParameterTypes.Length);
                il.Emit(OpCodes.Newarr, typeof(object));
                if (methodParameterTypes.Length > 0)
                {
                    for (var i = 0; i < methodParameterTypes.Length; i++)
                    {
                        il.Emit(OpCodes.Dup);
                        il.Emit(OpCodes.Ldc_I4, i);
                        il.Emit(OpCodes.Ldarg, i + 1);
                        if (methodParameterTypes[i].IsValueType)
                        {
                            il.Emit(OpCodes.Box, methodParameterTypes[i].UnderlyingSystemType);
                        }

                        il.Emit(OpCodes.Stelem_Ref);
                    }
                }
                il.Emit(OpCodes.Stloc, localParameters);

                // var invocation = new MethodInvocation(method, methodBase, this, this, parameters);
                var localAspectInvocation = il.DeclareLocal(typeof(AspectInvocation));

                il.Emit(OpCodes.Ldloc, localCurrentMethod);
                il.Emit(OpCodes.Ldloc, localMethodBase);
                il.EmitThis();

                il.EmitThis();
                if (null != targetField)
                {
                    il.Emit(OpCodes.Ldfld, targetField);
                }

                il.Emit(OpCodes.Ldloc, localParameters);

                il.New(MethodInvokeHelper.AspectInvocationConstructor);
                il.Emit(OpCodes.Stloc, localAspectInvocation);

                // AspectDelegate.Invoke(invocation);
                il.Emit(OpCodes.Ldloc, localAspectInvocation);
                il.Call(MethodInvokeHelper.InvokeAspectDelegateMethod);

                if (method.ReturnType != typeof(void))
                {
                    // load return value
                    il.Emit(OpCodes.Ldloc, localAspectInvocation);

                    il.EmitCall(OpCodes.Callvirt, MethodInvokeHelper.GetInvocationReturnValueMethod, Type.EmptyTypes);

                    if (method.ReturnType.IsValueType)
                    {
                        il.EmitCastToType(typeof(object), method.ReturnType);
                    }

                    il.Emit(OpCodes.Stloc, localReturnValue);
                    il.Emit(OpCodes.Ldloc, localReturnValue);
                }

                il.Emit(OpCodes.Ret);

                return(methodBuilder);
            }
コード例 #4
0
        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);
        }