Beispiel #1
0
        public void UsingClassEmitterForInterfaces()
        {
            ClassEmitter emitter = new ClassEmitter(
                generator.ProxyBuilder.ModuleScope,
                "IFoo",
                null,
                Type.EmptyTypes,
                TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public,
                false
                );

            emitter.CreateMethod(
                "MyMethod",
                MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
                typeof(void),
                Type.EmptyTypes
                );
            Type t = emitter.BuildType();

            Assert.IsTrue(t.IsInterface);
            MethodInfo method = t.GetMethod("MyMethod");

            Assert.IsNotNull(method);
        }
        public virtual void Generate(ClassEmitter @class)
        {
            foreach (var method in methods)
            {
                if (!method.Standalone)
                {
                    continue;
                }

                ImplementMethod(method,
                                @class,
                                @class.CreateMethod);
            }

            foreach (var property in properties)
            {
                ImplementProperty(@class, property);
            }

            foreach (var @event in events)
            {
                ImplementEvent(@class, @event);
            }
        }
Beispiel #3
0
        private Type GetInvocationType(MetaMethod method, ClassEmitter emitter, ProxyGenerationOptions options)
        {
            var scope = emitter.ModuleScope;

            Type[] invocationInterfaces;
            if (canChangeTarget)
            {
                invocationInterfaces = new[] { typeof(IInvocation), typeof(IChangeProxyTarget) };
            }
            else
            {
                invocationInterfaces = new[] { typeof(IInvocation) };
            }
            var key = new CacheKey(method.Method, CompositionInvocationTypeGenerator.BaseType, invocationInterfaces, null);

            // no locking required as we're already within a lock

            var invocation = scope.GetFromCache(key);

            if (invocation != null)
            {
                return(invocation);
            }

            invocation = new CompositionInvocationTypeGenerator(method.Method.DeclaringType,
                                                                method,
                                                                method.Method,
                                                                canChangeTarget,
                                                                null)
                         .Generate(emitter, options, namingScope)
                         .BuildType();

            scope.RegisterInCache(key, invocation);

            return(invocation);
        }
        protected override void CustomizeGetObjectData(
            CodeBuilder codebuilder,
            ArgumentReference serializationInfo,
            ArgumentReference streamingContext,
            ClassEmitter emitter
            )
        {
            codebuilder.AddStatement(
                new MethodInvocationExpression(
                    serializationInfo,
                    SerializationInfoMethods.AddValue_Bool,
                    new LiteralStringExpression("__delegateToBase"),
                    new LiteralBoolExpression(delegateToBaseGetObjectData)
                    )
                );

            if (delegateToBaseGetObjectData == false)
            {
                EmitCustomGetObjectData(codebuilder, serializationInfo);
                return;
            }

            EmitCallToBaseGetObjectData(codebuilder, serializationInfo, streamingContext);
        }
Beispiel #5
0
        public void InstanceMethodArguments()
        {
            ClassEmitter emitter = new ClassEmitter(
                generator.ProxyBuilder.ModuleScope,
                "Foo",
                typeof(List <object>),
                Type.EmptyTypes
                );
            MethodEmitter methodEmitter = emitter.CreateMethod(
                "InstanceMethod",
                MethodAttributes.Public,
                typeof(string),
                typeof(string)
                );

            methodEmitter.CodeBuilder.AddStatement(new ReturnStatement(methodEmitter.Arguments[0]));
            Type   t        = emitter.BuildType();
            object instance = Activator.CreateInstance(t);

            Assert.AreEqual(
                "six",
                t.GetMethod("InstanceMethod").Invoke(instance, new object[] { "six" })
                );
        }
Beispiel #6
0
        protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class,
                                                              OverrideMethodDelegate overrideMethod)
        {
            if (method.Ignore)
            {
                return(null);
            }

            var methodIsDirectlyAccessible = IsDirectlyAccessible(method);

            if (!method.Proxyable)
            {
                if (methodIsDirectlyAccessible)
                {
                    return(new ForwardingMethodGenerator(method, overrideMethod, (c, m) => c.GetField("__target")));
                }
                else
                {
                    return(IndirectlyCalledMethodGenerator(method, @class, overrideMethod, skipInterceptors: true));
                }
            }

            if (!methodIsDirectlyAccessible)
            {
                return(IndirectlyCalledMethodGenerator(method, @class, overrideMethod));
            }

            var invocation = GetInvocationType(method, @class);

            return(new MethodWithInvocationGenerator(method,
                                                     @class.GetField("__interceptors"),
                                                     invocation,
                                                     (c, m) => c.GetField("__target"),
                                                     overrideMethod,
                                                     null));
        }
Beispiel #7
0
        protected void GenerateConstructor(ClassEmitter emitter, ConstructorInfo baseConstructor,
                                           params FieldReference[] fields)
        {
            ArgumentReference[] args;
            ParameterInfo[]     baseConstructorParams = null;

            if (baseConstructor != null)
            {
                baseConstructorParams = baseConstructor.GetParameters();
            }

            if (baseConstructorParams != null && baseConstructorParams.Length != 0)
            {
                args = new ArgumentReference[fields.Length + baseConstructorParams.Length];

                var offset = fields.Length;
                for (var i = offset; i < offset + baseConstructorParams.Length; i++)
                {
                    var paramInfo = baseConstructorParams[i - offset];
                    args[i] = new ArgumentReference(paramInfo.ParameterType);
                }
            }
            else
            {
                args = new ArgumentReference[fields.Length];
            }

            for (var i = 0; i < fields.Length; i++)
            {
                args[i] = new ArgumentReference(fields[i].Reference.FieldType);
            }

            var constructor = emitter.CreateConstructor(args);

            if (baseConstructorParams != null && baseConstructorParams.Length != 0)
            {
                var last = baseConstructorParams.Last();
                if (last.ParameterType.GetTypeInfo().IsArray&& last.IsDefined(typeof(ParamArrayAttribute)))
                {
                    var parameter = constructor.ConstructorBuilder.DefineParameter(args.Length, ParameterAttributes.None, last.Name);
                    var builder   = AttributeUtil.CreateBuilder <ParamArrayAttribute>();
                    parameter.SetCustomAttribute(builder);
                }
            }

            for (var i = 0; i < fields.Length; i++)
            {
                constructor.CodeBuilder.AddStatement(new AssignStatement(fields[i], args[i].ToExpression()));
            }

            // Invoke base constructor

            if (baseConstructor != null)
            {
                Debug.Assert(baseConstructorParams != null);

                var slice = new ArgumentReference[baseConstructorParams.Length];
                Array.Copy(args, fields.Length, slice, 0, baseConstructorParams.Length);

                constructor.CodeBuilder.InvokeBaseConstructor(baseConstructor, slice);
            }
            else
            {
                constructor.CodeBuilder.InvokeBaseConstructor();
            }

            constructor.CodeBuilder.AddStatement(new ReturnStatement());
        }
Beispiel #8
0
 protected virtual void CreateFields(ClassEmitter emitter)
 {
     CreateOptionsField(emitter);
     CreateSelectorField(emitter);
     CreateInterceptorsField(emitter);
 }
 protected new void CreateInterceptorsField(ClassEmitter emitter)
 => emitter.CreateField("__interceptors", Options.InterceptorType.MakeArrayType());
Beispiel #10
0
 private Reference GetTarget(ClassEmitter @class, MethodInfo method)
 {
     return(new AsTypeReference(@class.GetField("__target"), method.DeclaringType));
 }
Beispiel #11
0
        protected override void CustomizeGetObjectData(CodeBuilder codebuilder, ArgumentReference serializationInfo,
                                                       ArgumentReference streamingContext, ClassEmitter emitter)
        {
            var targetField = emitter.GetField("__target");

            codebuilder.AddStatement(
                new MethodInvocationExpression(
                    serializationInfo,
                    SerializationInfoMethods.AddValue_Object,
                    new LiteralStringExpression("__targetFieldType"),
                    new LiteralStringExpression(targetField.Reference.FieldType.AssemblyQualifiedName)));

            codebuilder.AddStatement(
                new MethodInvocationExpression(
                    serializationInfo,
                    SerializationInfoMethods.AddValue_Object,
                    new LiteralStringExpression("__theInterface"),
                    new LiteralStringExpression(targetType.AssemblyQualifiedName)));
        }
Beispiel #12
0
        protected void ImplementGetObjectData(ClassEmitter emitter)
        {
            var getObjectData = emitter.CreateMethod(
                "GetObjectData",
                typeof(void),
                new[] { typeof(SerializationInfo), typeof(StreamingContext) }
                );
            var info = getObjectData.Arguments[0];

            var typeLocal = getObjectData.CodeBuilder.DeclareLocal(typeof(Type));

            getObjectData.CodeBuilder.AddStatement(
                new AssignStatement(
                    typeLocal,
                    new MethodInvocationExpression(
                        null,
                        TypeMethods.StaticGetType,
                        new LiteralStringExpression(
                            typeof(ProxyObjectReference).AssemblyQualifiedName
                            ),
                        new LiteralBoolExpression(true),
                        new LiteralBoolExpression(false)
                        )
                    )
                );

            getObjectData.CodeBuilder.AddStatement(
                new MethodInvocationExpression(info, SerializationInfoMethods.SetType, typeLocal)
                );

            foreach (var field in emitter.GetAllFields())
            {
                if (field.Reference.IsStatic)
                {
                    continue;
                }
                if (field.Reference.IsNotSerialized)
                {
                    continue;
                }
                AddAddValueInvocation(info, getObjectData, field);
            }

            var interfacesLocal = getObjectData.CodeBuilder.DeclareLocal(typeof(string[]));

            getObjectData.CodeBuilder.AddStatement(
                new AssignStatement(
                    interfacesLocal,
                    new NewArrayExpression(interfaces.Length, typeof(string))
                    )
                );

            for (var i = 0; i < interfaces.Length; i++)
            {
                getObjectData.CodeBuilder.AddStatement(
                    new AssignArrayStatement(
                        interfacesLocal,
                        i,
                        new LiteralStringExpression(interfaces[i].AssemblyQualifiedName)
                        )
                    );
            }

            getObjectData.CodeBuilder.AddStatement(
                new MethodInvocationExpression(
                    info,
                    SerializationInfoMethods.AddValue_Object,
                    new LiteralStringExpression("__interfaces"),
                    interfacesLocal
                    )
                );

            getObjectData.CodeBuilder.AddStatement(
                new MethodInvocationExpression(
                    info,
                    SerializationInfoMethods.AddValue_Object,
                    new LiteralStringExpression("__baseType"),
                    new LiteralStringExpression(emitter.BaseType.AssemblyQualifiedName)
                    )
                );

            getObjectData.CodeBuilder.AddStatement(
                new MethodInvocationExpression(
                    info,
                    SerializationInfoMethods.AddValue_Object,
                    new LiteralStringExpression("__proxyGenerationOptions"),
                    emitter.GetField("proxyGenerationOptions")
                    )
                );

            getObjectData.CodeBuilder.AddStatement(
                new MethodInvocationExpression(
                    info,
                    SerializationInfoMethods.AddValue_Object,
                    new LiteralStringExpression("__proxyTypeId"),
                    new LiteralStringExpression(proxyTypeId)
                    )
                );

            CustomizeGetObjectData(
                getObjectData.CodeBuilder,
                info,
                getObjectData.Arguments[1],
                emitter
                );

            getObjectData.CodeBuilder.AddStatement(new ReturnStatement());
        }
Beispiel #13
0
 protected override Expression GetTargetReferenceExpression(ClassEmitter emitter)
 {
     return(emitter.GetField("__target").ToExpression());
 }
 protected override void CreateFields(ClassEmitter emitter)
 {
     base.CreateFields(emitter);
     CreateTargetField(emitter);
 }
Beispiel #15
0
        private FieldReference BuildTargetField(ClassEmitter @class, Type type)
        {
            var name = "__mixin_" + type.FullName.Replace(".", "_");

            return(@class.CreateField(namingScope.GetUniqueName(name), type));
        }
Beispiel #16
0
 protected abstract void CustomizeGetObjectData(
     CodeBuilder builder,
     ArgumentReference serializationInfo,
     ArgumentReference streamingContext,
     ClassEmitter emitter
     );
Beispiel #17
0
 public virtual void Generate(ClassEmitter @class)
 {
     ImplementGetObjectData(@class);
 }
Beispiel #18
0
        protected void GenerateConstructor(ClassEmitter emitter, ConstructorInfo baseConstructor,
                                           params FieldReference[] fields)
        {
            ArgumentReference[] args;
            ParameterInfo[]     baseConstructorParams = null;

            if (baseConstructor != null)
            {
                baseConstructorParams = baseConstructor.GetParameters();
            }

            if (baseConstructorParams != null && baseConstructorParams.Length != 0)
            {
                args = new ArgumentReference[fields.Length + baseConstructorParams.Length];

                var offset = fields.Length;
                for (var i = offset; i < offset + baseConstructorParams.Length; i++)
                {
                    var paramInfo = baseConstructorParams[i - offset];
                    args[i] = new ArgumentReference(paramInfo.ParameterType);
                }
            }
            else
            {
                args = new ArgumentReference[fields.Length];
            }

            for (var i = 0; i < fields.Length; i++)
            {
                args[i] = new ArgumentReference(fields[i].Reference.FieldType);
            }

            var constructor = emitter.CreateConstructor(args);

            if (baseConstructorParams != null && baseConstructorParams.Length != 0)
            {
                var offset = 1 + fields.Length;
                for (int i = 0, n = baseConstructorParams.Length; i < n; ++i)
                {
                    var parameterBuilder = constructor.ConstructorBuilder.DefineParameter(offset + i, baseConstructorParams[i].Attributes, baseConstructorParams[i].Name);
                    foreach (var attribute in baseConstructorParams[i].GetNonInheritableAttributes())
                    {
                        parameterBuilder.SetCustomAttribute(attribute.Builder);
                    }
                }
            }

            for (var i = 0; i < fields.Length; i++)
            {
                constructor.CodeBuilder.AddStatement(new AssignStatement(fields[i], args[i].ToExpression()));
            }

            // Invoke base constructor

            if (baseConstructor != null)
            {
                Debug.Assert(baseConstructorParams != null);

                var slice = new ArgumentReference[baseConstructorParams.Length];
                Array.Copy(args, fields.Length, slice, 0, baseConstructorParams.Length);

                constructor.CodeBuilder.InvokeBaseConstructor(baseConstructor, slice);
            }
            else
            {
                constructor.CodeBuilder.InvokeBaseConstructor();
            }

            constructor.CodeBuilder.AddStatement(new ReturnStatement());
        }
Beispiel #19
0
        protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class,
                                                                INamingScope namingScope)
        {
            var targetReference = getTargetReference(@class, MethodToOverride);
            var arguments       = ArgumentsUtil.ConvertToArgumentReferenceExpression(MethodToOverride.GetParameters());

            emitter.CodeBuilder.AddStatement(new ReturnStatement(
                                                 new MethodInvocationExpression(
                                                     targetReference,
                                                     MethodToOverride,
                                                     arguments)
            {
                VirtualCall = true
            }));
            return(emitter);
        }
        protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, INamingScope namingScope)
        {
            var invocationType = invocation;

            Trace.Assert(MethodToOverride.IsGenericMethod == invocationType.IsGenericTypeDefinition);
            var genericArguments = Type.EmptyTypes;

            var constructor = invocation.GetConstructors()[0];

            Expression proxiedMethodTokenExpression;

            if (MethodToOverride.IsGenericMethod)
            {
                // bind generic method arguments to invocation's type arguments
                genericArguments = emitter.MethodBuilder.GetGenericArguments();
                invocationType   = invocationType.MakeGenericType(genericArguments);
                constructor      = TypeBuilder.GetConstructor(invocationType, constructor);

                // Not in the cache: generic method
                proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericArguments));
            }
            else
            {
                var proxiedMethodToken = @class.CreateStaticField(namingScope.GetUniqueName("token_" + MethodToOverride.Name), typeof(MethodInfo));
                @class.ClassConstructor.CodeBuilder.AddStatement(new AssignStatement(proxiedMethodToken, new MethodTokenExpression(MethodToOverride)));

                proxiedMethodTokenExpression = proxiedMethodToken.ToExpression();
            }

            var methodInterceptors = SetMethodInterceptors(@class, namingScope, emitter, proxiedMethodTokenExpression);

            var dereferencedArguments = IndirectReference.WrapIfByRef(emitter.Arguments);
            var hasByRefArguments     = HasByRefArguments(emitter.Arguments);

            var arguments     = GetCtorArguments(@class, proxiedMethodTokenExpression, dereferencedArguments, methodInterceptors);
            var ctorArguments = ModifyArguments(@class, arguments);

            var invocationLocal = emitter.CodeBuilder.DeclareLocal(invocationType);

            emitter.CodeBuilder.AddStatement(new AssignStatement(invocationLocal,
                                                                 new NewInstanceExpression(constructor, ctorArguments)));

            if (MethodToOverride.ContainsGenericParameters)
            {
                EmitLoadGenricMethodArguments(emitter, MethodToOverride.MakeGenericMethod(genericArguments), invocationLocal);
            }

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new TryStatement());
            }

            var proceed = new ExpressionStatement(new MethodInvocationExpression(invocationLocal, InvocationMethods.Proceed));

            emitter.CodeBuilder.AddStatement(proceed);

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new FinallyStatement());
            }

            GeneratorUtil.CopyOutAndRefParameters(dereferencedArguments, invocationLocal, MethodToOverride, emitter);

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new EndExceptionBlockStatement());
            }

            if (MethodToOverride.ReturnType != typeof(void))
            {
                var getRetVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue);

                // Emit code to ensure a value type return type is not null, otherwise the cast will cause a null-deref
                if (emitter.ReturnType.IsValueType && !emitter.ReturnType.IsNullableType())
                {
                    LocalReference returnValue = emitter.CodeBuilder.DeclareLocal(typeof(object));
                    emitter.CodeBuilder.AddStatement(new AssignStatement(returnValue, getRetVal));

                    emitter.CodeBuilder.AddExpression(new IfNullExpression(returnValue, new ThrowStatement(typeof(InvalidOperationException),
                                                                                                           "Interceptors failed to set a return value, or swallowed the exception thrown by the target")));
                }

                // Emit code to return with cast from ReturnValue
                emitter.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(emitter.ReturnType, getRetVal)));
            }
            else
            {
                emitter.CodeBuilder.AddStatement(new ReturnStatement());
            }

            return(emitter);
        }
        protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class,
                                                                ProxyGenerationOptions options, INamingScope namingScope)
        {
            var targetReference = getTargetReference(@class, MethodToOverride);

            emitter.CodeBuilder.AddStatement(
                new ExpressionStatement(
                    new IfNullExpression(targetReference, IfNull(emitter.ReturnType), IfNotNull(targetReference))));
            return(emitter);
        }
Beispiel #22
0
 public Expression[] GetConstructorInvocationArguments(Expression[] arguments, ClassEmitter proxy)
 {
     return(arguments);
 }
Beispiel #23
0
 private Expression GetTargetExpression(ClassEmitter @class, MethodInfo method)
 {
     return(GetTarget(@class, method).ToExpression());
 }
Beispiel #24
0
 protected void GenerateConstructor(ClassEmitter emitter, ConstructorInfo baseConstructor,
                                    params FieldReference[] fields)
 {
     GenerateConstructor(emitter, baseConstructor, ProxyConstructorImplementation.CallBase, fields);
 }
        protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class,
                                                                ProxyGenerationOptions options, INamingScope namingScope)
        {
            var invocationType = invocation;

            Trace.Assert(MethodToOverride.IsGenericMethod == invocationType.IsGenericTypeDefinition());
            var genericArguments = TypeExtender.EmptyTypes;

            var constructor = invocation.GetConstructors()[0];

            Expression proxiedMethodTokenExpression;

            if (MethodToOverride.IsGenericMethod)
            {
                // bind generic method arguments to invocation's type arguments
                genericArguments = emitter.MethodBuilder.GetGenericArguments();
                invocationType   = invocationType.MakeGenericType(genericArguments);

                constructor = TypeBuilder.GetConstructor(invocationType, constructor);

                // Not in the cache: generic method
                proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericArguments));
            }
            else
            {
                var proxiedMethodToken = @class.CreateStaticField(namingScope.GetUniqueName("token_" + MethodToOverride.Name),
                                                                  typeof(IMethodInfo));

                @class.ClassConstructor.CodeBuilder.AddStatement(new AssignStatement(proxiedMethodToken,
                                                                                     new MethodTokenExpression(MethodToOverride)));

                proxiedMethodTokenExpression = proxiedMethodToken.ToExpression();
            }

            var dereferencedArguments = IndirectReference.WrapIfByRef(emitter.Arguments);
            var hasByRefArguments     = HasByRefArguments(emitter.Arguments);

            var arguments = GetCtorArguments(@class, namingScope, proxiedMethodTokenExpression,
                                             dereferencedArguments);
            var ctorArguments = ModifyArguments(@class, arguments);

            var invocationLocal = emitter.CodeBuilder.DeclareLocal(invocationType);

            emitter.CodeBuilder.AddStatement(new AssignStatement(invocationLocal,
                                                                 new NewInstanceExpression(constructor, ctorArguments)));

            if (MethodToOverride.ContainsGenericParameters)
            {
                EmitLoadGenricMethodArguments(emitter, MethodToOverride.MakeGenericMethod(genericArguments), invocationLocal);
            }

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new TryStatement());
            }

            var proceed = new ExpressionStatement(new MethodInvocationExpression(invocationLocal, InvocationMethods.Proceed));

            emitter.CodeBuilder.AddStatement(proceed);

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new FinallyStatement());
            }

            GeneratorUtil.CopyOutAndRefParameters(dereferencedArguments, invocationLocal, MethodToOverride, emitter);

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new EndExceptionBlockStatement());
            }

            if (MethodToOverride.ReturnType != typeof(void))
            {
                var getRetVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue);
                emitter.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(emitter.ReturnType, getRetVal)));
            }
            else
            {
                emitter.CodeBuilder.AddStatement(new ReturnStatement());
            }

            return(emitter);
        }
Beispiel #26
0
        protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class,
                                                                ProxyGenerationOptions options, INamingScope namingScope)
        {
            InitOutParameters(emitter, MethodToOverride.GetParameters());

            if (emitter.ReturnType == typeof(void))
            {
                emitter.CodeBuilder.AddStatement(new ReturnStatement());
            }
            else
            {
                emitter.CodeBuilder.AddStatement(new ReturnStatement(new DefaultValueExpression(emitter.ReturnType)));
            }

            return(emitter);
        }
Beispiel #27
0
 protected FieldReference CreateOptionsField(ClassEmitter emitter)
 {
     return(emitter.CreateStaticField("proxyGenerationOptions", typeof(ProxyGenerationOptions)));
 }
 protected override Reference GetTargetReference(ClassEmitter emitter)
 {
     return(emitter.GetField("__target"));
 }
Beispiel #29
0
 protected ConstructorEmitter GenerateStaticConstructor(ClassEmitter emitter)
 {
     return(emitter.CreateTypeConstructor());
 }
 protected abstract Expression GetTargetReferenceExpression(ClassEmitter emitter);