Esempio n. 1
0
 public void SetupParameters(MethodBuilder methodBuilder, GenericParameterMapper parentMapper)
 {
     if (this._methodToOverride.IsGenericMethod)
     {
         Type[]   genericArguments = this._methodToOverride.GetGenericArguments();
         string[] names            = (from t in genericArguments
                                      select t.Name).ToArray();
         GenericTypeParameterBuilder[] builders = methodBuilder.DefineGenericParameters(names);
         for (int i = 0; i < genericArguments.Length; i++)
         {
             builders[i].SetGenericParameterAttributes(genericArguments[i].GenericParameterAttributes);
             Type[] source = (from ct in genericArguments[i].GetGenericParameterConstraints()
                              select parentMapper.Map(ct)).ToArray();
             Type[] interfaceConstraints = (from t in source
                                            where t.IsInterface
                                            select t).ToArray();
             Type baseConstraint = (from t in source
                                    where !t.IsInterface
                                    select t).FirstOrDefault();
             if (baseConstraint != (Type)null)
             {
                 builders[i].SetBaseTypeConstraint(baseConstraint);
             }
             if (interfaceConstraints.Length != 0)
             {
                 builders[i].SetInterfaceConstraints(interfaceConstraints);
             }
         }
         this._genericParameterMapper = new GenericParameterMapper(genericArguments, builders.Cast <Type>().ToArray(), parentMapper);
     }
     else
     {
         this._genericParameterMapper = parentMapper;
     }
 }
Esempio n. 2
0
        private void CreateTypeBuilder()
        {
            TypeAttributes newAttributes = _typeToIntercept.Attributes;

            newAttributes = FilterTypeAttributes(newAttributes);
            Type          baseClass     = GetGenericType(_typeToIntercept);
            ModuleBuilder moduleBuilder = GetModuleBuilder();

            _typeBuilder    = moduleBuilder.DefineType($"DynamicModule.Wrapped_{_typeToIntercept.Name}_{Guid.NewGuid().ToString("N")}", newAttributes, baseClass);
            _mainTypeMapper = DefineGenericArguments(_typeBuilder, baseClass);
            if (_typeToIntercept.IsGenericType)
            {
                Type   definition       = _typeToIntercept.GetGenericTypeDefinition();
                Type[] mappedParameters = (from t in definition.GetGenericArguments() select _mainTypeMapper.Map(t)).ToArray();
                _targetType = definition.MakeGenericType(mappedParameters);
            }
            else
            {
                _targetType = _typeToIntercept;
            }
        }
 public GenericParameterMapper(Type type, GenericParameterMapper parent)
 {
     if (type == null)
     {
         throw new ArgumentNullException(nameof(type));
     }
     if (type.IsGenericType)
     {
         if (type.IsGenericTypeDefinition)
         {
             throw new ArgumentException("Cannot Map Generic Type Definition");
         }
         this._parent        = parent;
         this._localMappings = GenericParameterMapper.CreateMappings(type.GetGenericTypeDefinition().GetGenericArguments(), type.GetGenericArguments());
     }
     else
     {
         this._localMappings = GenericParameterMapper.EmptyMappings;
         this._parent        = null;
     }
 }
        public InterceptionAttributeAnalysis(TypeBuilder typeBuilder, Type typeToIntercept, GenericParameterMapper targetTypeParameterMapper)
        {
            _typeBuilder       = typeBuilder;
            _typeToIntercept   = typeToIntercept;
            _targetMethodInfos = GetMethodsToIntercept();
            if (!HasInterceptionAttribute(_typeToIntercept))
            {
                _targetMethodInfos = _targetMethodInfos.Where(methodInfo => HasInterceptionAttribute(methodInfo));
            }
            var targetType = _typeToIntercept;

            if (_typeToIntercept.IsGenericType)
            {
                targetType = ((ModuleBuilder)_typeBuilder.Module).DefineType($"__Anonymous__GenericType__{_typeToIntercept.Name}", TypeAttributes.Public | TypeAttributes.BeforeFieldInit | TypeAttributes.Sealed).CreateType();
            }
            var mapType = typeof(ProxyMap <>).MakeGenericType(targetType);

            _mapFieldInfo              = mapType.GetField("Map", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
            _proxyDelegates            = (List <ProxyDelegate>)_mapFieldInfo.GetValue(null);
            _mapGetMethod              = _mapFieldInfo.FieldType.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new Type[] { typeof(int) }, new ParameterModifier[0]);
            methodCount                = _proxyDelegates.Count;
            _targetTypeParameterMapper = targetTypeParameterMapper;
        }
        /*Derived Method process:
         * baseMethod.ReturnType DerivedMethod(baseMethod.Parameters)
         * {
         *     IMethodInvocation input = Wrapped(baseMethod.Parameters);
         *     var methodReturn = @delegate(input);
         *     if(methodReturn.Exception==null)
         *         return (baseMethod.ReturnType)methodReturn.ReturnValue;
         *     throw methodReturn.Exception;
         * }
         */
        private void AddMethod(MethodInfo methodInfo, InvokeHandlerDelegate @delegate)
        {
            var attr          = methodInfo.Attributes & ~MethodAttributes.VtableLayoutMask & ~MethodAttributes.Abstract;
            var methodBuilder = _typeBuilder.DefineMethod(methodInfo.Name, attr);

            Type declaringType = methodInfo.DeclaringType;
            GenericParameterMapper        mapper     = (declaringType.IsGenericType && declaringType != methodInfo.ReflectedType) ? new GenericParameterMapper(declaringType, _targetTypeParameterMapper) : _targetTypeParameterMapper;
            MethodOverrideParameterMapper paraMapper = new MethodOverrideParameterMapper(methodInfo);

            paraMapper.SetupParameters(methodBuilder, mapper);
            methodBuilder.SetReturnType(paraMapper.GetReturnType());
            methodBuilder.SetParameters(methodInfo.GetParameters().Select(pi => paraMapper.GetParameterType(pi.ParameterType)).ToArray());
            var il = methodBuilder.GetILGenerator();

            il.DeclareLocal(typeof(ProxyDelegate));     //local 0
            il.DeclareLocal(typeof(MethodInvocation));  //local 1
            il.DeclareLocal(typeof(IMethodReturn));     //local 2
            //add ProxyDelegate to ProxyMap
            _proxyDelegates.Add(new ProxyDelegate {
                @delegate = @delegate, methodInfo = methodInfo
            });

            var parameterInfos  = methodInfo.GetParameters();
            int parameterLength = parameterInfos.Length;
            int paramNum        = 1;

            foreach (ParameterInfo pi2 in parameterInfos)
            {
                methodBuilder.DefineParameter(paramNum++, pi2.Attributes, pi2.Name);
            }
            //the ref parameter(ref or out) set a default value
            for (int i = 0; i < parameterLength; i++)
            {
                if (paraMapper.GetParameterType(parameterInfos[i].ParameterType).IsByRef)
                {
                    EmitLoadArgument(il, i);
                    il.Emit(OpCodes.Initobj, paraMapper.GetElementType(parameterInfos[i].ParameterType));
                }
            }
            //ProxyDelegate proxyDelegate=ProxyMap<$Type>.Map[$methodCount];
            il.Emit(OpCodes.Ldsfld, _mapFieldInfo);
            EmitLoadConstant(il, methodCount);
            il.Emit(OpCodes.Callvirt, _mapGetMethod);
            il.Emit(OpCodes.Stloc_0);   //set the value to local 0

            il.Emit(OpCodes.Ldarg_0);   //load this
            il.Emit(OpCodes.Ldloc_0);   //load local 0
            il.Emit(OpCodes.Ldfld, typeof(ProxyDelegate).GetField("methodInfo"));

            //new object[]
            EmitLoadConstant(il, parameterLength);
            il.Emit(OpCodes.Newarr, typeof(object));

            for (int i = 0; i < parameterLength; i++)
            {
                il.Emit(OpCodes.Dup);//copy the value to the top of the stack
                EmitLoadConstant(il, i);
                EmitLoadArgument(il, i);
                var parameterType = paraMapper.GetParameterType(parameterInfos[i].ParameterType);
                var isByRef       = parameterType.IsByRef;
                if (isByRef)
                {
                    parameterType = parameterType.GetElementType();
                }
                if (parameterInfos[i].ParameterType.IsValueType || parameterInfos[i].ParameterType.IsGenericParameter)
                {
                    il.Emit(OpCodes.Box, paraMapper.GetParameterType(parameterInfos[i].ParameterType));
                }
                else if (isByRef)
                {
                    il.Emit(OpCodes.Ldobj, parameterType);
                    if (parameterType.IsValueType || parameterType.IsGenericParameter)
                    {
                        il.Emit(OpCodes.Box, parameterType);
                    }
                }
                il.Emit(OpCodes.Stelem_Ref);
            }
            il.Emit(OpCodes.Newobj, typeof(MethodInvocation).GetConstructor(new Type[] { typeof(object), typeof(MethodBase), typeof(object[]) })); //call new MethodInvocation()
            il.Emit(OpCodes.Stloc_1);                                                                                                              //set new obj to local 1
            //IMethodReturn r=proxyDelegate.@delegate(input)
            il.Emit(OpCodes.Ldloc_0);
            il.Emit(OpCodes.Ldfld, typeof(ProxyDelegate).GetField("delegate"));
            il.Emit(OpCodes.Ldloc_1);
            il.Emit(OpCodes.Callvirt, @delegate.GetType().GetMethod("Invoke"));
            il.Emit(OpCodes.Stloc_2);
            // if (r.Exception==null)
            il.Emit(OpCodes.Ldloc_2);
            il.Emit(OpCodes.Callvirt, typeof(IMethodReturn).GetMethod("get_Exception", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance));
            Label lbTrue = il.DefineLabel();

            il.Emit(OpCodes.Brtrue_S, lbTrue);
            //false
            //handle ref or out parameters
            var getOutputs   = typeof(IMethodReturn).GetMethod("get_Outputs", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            var getItem      = typeof(IParameterCollection).GetMethod("get_Item", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(int) }, new ParameterModifier[0]);
            int refParamNums = 0;

            for (int i = 0; i < parameterLength; i++)
            {
                var parameterType = paraMapper.GetParameterType(parameterInfos[i].ParameterType);
                if (parameterType.IsByRef)
                {
                    EmitLoadArgument(il, i);
                    il.Emit(OpCodes.Ldloc_2);
                    il.Emit(OpCodes.Callvirt, getOutputs);
                    EmitLoadConstant(il, refParamNums++);
                    il.Emit(OpCodes.Callvirt, getItem);
                    var elementType = parameterType.GetElementType();
                    if (elementType.IsValueType || elementType.IsGenericParameter)
                    {
                        il.Emit(OpCodes.Unbox_Any, elementType);
                    }
                    else
                    {
                        il.Emit(OpCodes.Castclass, elementType);
                    }
                    il.Emit(OpCodes.Stobj, elementType);
                }
            }
            //return ($ReturnType)r.ReturnValue;
            var returnType = paraMapper.GetReturnType();

            if (returnType != typeof(void))
            {
                il.Emit(OpCodes.Ldloc_2);
                il.Emit(OpCodes.Callvirt, typeof(IMethodReturn).GetMethod("get_ReturnValue"));
                if (returnType.IsValueType || returnType.IsGenericParameter)
                {
                    il.Emit(OpCodes.Unbox_Any, returnType);
                }
                else
                {
                    il.Emit(OpCodes.Castclass, returnType);
                }
            }
            il.Emit(OpCodes.Ret);
            //ture
            //throw r.Exception
            il.MarkLabel(lbTrue);
            il.Emit(OpCodes.Ldloc_2);
            il.Emit(OpCodes.Callvirt, typeof(IMethodReturn).GetMethod("get_Exception", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance));
            il.Emit(OpCodes.Throw);
            //increase methodCount
            methodCount++;
        }
 public GenericParameterMapper(Type[] reflectedParameters, Type[] generatedParameters, GenericParameterMapper parent)
 {
     this._parent        = parent;
     this._localMappings = GenericParameterMapper.CreateMappings(reflectedParameters, generatedParameters);
 }