protected virtual ITypeContributor AddMappingForTargetType(IDictionary<Type, ITypeContributor> typeImplementerMapping,
		                                                           Type proxyTargetType, ICollection<Type> targetInterfaces,
		                                                           ICollection<Type> additionalInterfaces,
		                                                           INamingScope namingScope)
		{
			var contributor = new InterfaceProxyTargetContributor(proxyTargetType, AllowChangeTarget, namingScope)
			{ Logger = Logger };
			var proxiedInterfaces = targetType.GetAllInterfaces();
			foreach (var @interface in proxiedInterfaces)
			{
				contributor.AddInterfaceToProxy(@interface);
				AddMappingNoCheck(@interface, contributor, typeImplementerMapping);
			}

			foreach (var @interface in additionalInterfaces)
			{
				if (!ImplementedByTarget(targetInterfaces, @interface) || proxiedInterfaces.Contains(@interface))
				{
					continue;
				}

				contributor.AddInterfaceToProxy(@interface);
				AddMappingNoCheck(@interface, contributor, typeImplementerMapping);
			}
			return contributor;
		}
		public ClassProxyWithTargetTargetContributor(Type targetType, IList<MethodInfo> methodsToSkip,
		                                             INamingScope namingScope)
			: base(namingScope)
		{
			this.targetType = targetType;
			this.methodsToSkip = methodsToSkip;
		}
		protected virtual IEnumerable<Type> GetTypeImplementerMapping(out IEnumerable<ITypeContributor> contributors,
		                                                              INamingScope namingScope)
		{
			var methodsToSkip = new List<MethodInfo>();
			var proxyInstance = new ClassProxyInstanceContributor(targetType, methodsToSkip, Type.EmptyTypes,
			                                                      ProxyTypeConstants.ClassWithTarget);
			var proxyTarget = new DelegateProxyTargetContributor(targetType, namingScope) { Logger = Logger };
			IDictionary<Type, ITypeContributor> typeImplementerMapping = new Dictionary<Type, ITypeContributor>();

			// Order of interface precedence:
			// 1. first target, target is not an interface so we do nothing
			// 2. then mixins - we support none so we do nothing
			// 3. then additional interfaces - we support none so we do nothing
#if !SILVERLIGHT
			// 4. plus special interfaces
			if (targetType.IsSerializable)
			{
				AddMappingForISerializable(typeImplementerMapping, proxyInstance);
			}
#endif
			AddMappingNoCheck(typeof(IProxyTargetAccessor), proxyInstance, typeImplementerMapping);

			contributors = new List<ITypeContributor>
			{
				proxyTarget,
				proxyInstance
			};
			return typeImplementerMapping.Keys;
		}
 public InterfaceProxyWithOptionalTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget,
                                                    GetTargetReferenceDelegate getTargetReference)
     : base(namingScope, getTarget)
 {
     this.getTargetReference = getTargetReference;
     canChangeTarget = true;
 }
		public InvocationWithDelegateContributor(Type delegateType, Type targetType,MetaMethod method, INamingScope namingScope)
		{
			Debug.Assert(delegateType.IsGenericType == false, "delegateType.IsGenericType == false");
			this.delegateType = delegateType;
			this.targetType = targetType;
			this.method = method;
			this.namingScope = namingScope;
		}
		private Type GenerateType(string name, INamingScope namingScope)
		{
			IEnumerable<ITypeContributor> contributors;
			var implementedInterfaces = GetTypeImplementerMapping(out contributors, namingScope);

			var model = new MetaType();
			// Collect methods
			foreach (var contributor in contributors)
			{
				contributor.CollectElementsToProxy(ProxyGenerationOptions.Hook, model);
			}
			ProxyGenerationOptions.Hook.MethodsInspected();

			var emitter = BuildClassEmitter(name, targetType, implementedInterfaces);

			CreateFields(emitter);
			CreateTypeAttributes(emitter);


			// Constructor
			var cctor = GenerateStaticConstructor(emitter);

			var targetField = CreateTargetField(emitter);
			var constructorArguments = new List<FieldReference> { targetField };

			foreach (var contributor in contributors)
			{
				contributor.Generate(emitter, ProxyGenerationOptions);

				// TODO: redo it
				if (contributor is MixinContributor)
				{
					constructorArguments.AddRange((contributor as MixinContributor).Fields);
				}
			}
			
			// constructor arguments
			var interceptorsField = emitter.GetField("__interceptors");
			constructorArguments.Add(interceptorsField);
			var selector = emitter.GetField("__selector");
			if (selector != null)
			{
				constructorArguments.Add(selector);
			}

			GenerateConstructors(emitter, targetType, constructorArguments.ToArray());
			GenerateParameterlessConstructor(emitter, targetType, interceptorsField);

			// Complete type initializer code body
			CompleteInitCacheMethod(cctor.CodeBuilder);

			// Crosses fingers and build type

			Type proxyType = emitter.BuildType();
			InitializeStaticFields(proxyType);
			return proxyType;
		}
		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;
		}
		protected override ITypeContributor AddMappingForTargetType(IDictionary<Type, ITypeContributor> interfaceTypeImplementerMapping, Type proxyTargetType, ICollection<Type> targetInterfaces, ICollection<Type> additionalInterfaces, INamingScope namingScope)
		{
			var contributor = new InterfaceProxyWithoutTargetContributor(namingScope, (c, m) => NullExpression.Instance)
			{ Logger = Logger };
			foreach (var @interface in TypeUtil.GetAllInterfaces(targetType))
			{
				contributor.AddInterfaceToProxy(@interface);
				AddMappingNoCheck(@interface, contributor, interfaceTypeImplementerMapping);
			}
			return contributor;
		}
		protected FieldReference BuildMethodInterceptorsField(ClassEmitter @class, MethodInfo method, INamingScope namingScope)
		{
			var methodInterceptors = @class.CreateField(
				namingScope.GetUniqueName(string.Format("interceptors_{0}", method.Name)),
				typeof(IInterceptor[]),
				false);
#if !SILVERLIGHT
			@class.DefineCustomAttributeFor<XmlIgnoreAttribute>(methodInterceptors);
#endif
			return methodInterceptors;
		}
		protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, 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 Type GenerateType(string typeName, Type proxyTargetType, Type[] interfaces,
		                                     INamingScope namingScope)
		{
			IEnumerable<ITypeContributor> contributors;
			var allInterfaces = GetTypeImplementerMapping(interfaces, targetType, out contributors, namingScope);
			var model = new MetaType();
			// collect elements
			foreach (var contributor in contributors)
			{
				contributor.CollectElementsToProxy(ProxyGenerationOptions.Hook, model);
			}

			ProxyGenerationOptions.Hook.MethodsInspected();

			ClassEmitter emitter;
			FieldReference interceptorsField;
			var baseType = Init(typeName, out emitter, proxyTargetType, out interceptorsField, allInterfaces);

			// Constructor

			var cctor = GenerateStaticConstructor(emitter);
			var mixinFieldsList = new List<FieldReference>();

			foreach (var contributor in contributors)
			{
				contributor.Generate(emitter, ProxyGenerationOptions);

				// TODO: redo it
				if (contributor is MixinContributor)
				{
					mixinFieldsList.AddRange((contributor as MixinContributor).Fields);
				}
			}

			var ctorArguments = new List<FieldReference>(mixinFieldsList) { interceptorsField, 
                targetField };
			var selector = emitter.GetField("__selector");
			if (selector != null)
			{
				ctorArguments.Add(selector);
			}

			GenerateConstructors(emitter, baseType, ctorArguments.ToArray());

			// Complete type initializer code body
			CompleteInitCacheMethod(cctor.CodeBuilder);

			// Crosses fingers and build type
			var generatedType = emitter.BuildType();

			InitializeStaticFields(generatedType);
			return generatedType;
		}
		protected override ITypeContributor AddMappingForTargetType(IDictionary<Type, ITypeContributor> typeImplementerMapping, Type proxyTargetType, ICollection<Type> targetInterfaces, ICollection<Type> additionalInterfaces, INamingScope namingScope)
		{
			WCFInterfaceProxyWithTargetInterfaceTargetContributor contributor = new WCFInterfaceProxyWithTargetInterfaceTargetContributor(proxyTargetType, this.AllowChangeTarget, namingScope)
			{
				Logger = base.Logger
			};
			foreach (Type @interface in base.targetType.GetAllInterfaces())
			{
				contributor.AddInterfaceToProxy(@interface);
				base.AddMappingNoCheck(@interface, contributor, typeImplementerMapping);
			}
			return contributor;
		}
		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;
		}
		protected override Type GenerateType(string typeName, Type proxyTargetType, Type[] interfaces, INamingScope namingScope)
		{
			IEnumerable<ITypeContributor> contributors;
			ClassEmitter emitter;
			FieldReference interceptorsField;
			IEnumerable<Type> allInterfaces = this.GetTypeImplementerMapping(interfaces, base.targetType, out contributors, namingScope);
			MetaType model = new MetaType();
			foreach (ITypeContributor contributor in contributors)
			{
				contributor.CollectElementsToProxy(base.ProxyGenerationOptions.Hook, model);
			}
			base.ProxyGenerationOptions.Hook.MethodsInspected();
			Type baseType = this.Init(typeName, out emitter, proxyTargetType, out interceptorsField, allInterfaces);
			ConstructorEmitter cctor = base.GenerateStaticConstructor(emitter);
			List<FieldReference> mixinFieldsList = new List<FieldReference>();
			foreach (ITypeContributor contributor in contributors)
			{
				contributor.Generate(emitter, base.ProxyGenerationOptions);
				if (contributor is MixinContributor)
				{
					mixinFieldsList.AddRange((contributor as MixinContributor).Fields);
				}
			}
			List<FieldReference> g__initLocalc = new List<FieldReference>(mixinFieldsList) {
            interceptorsField,
            base.targetField
        };
			List<FieldReference> ctorArguments = g__initLocalc;
			FieldReference selector = emitter.GetField("__selector");
			if (selector != null)
			{
				ctorArguments.Add(selector);
			}
			base.GenerateConstructors(emitter, baseType, ctorArguments.ToArray());
			base.CompleteInitCacheMethod(cctor.CodeBuilder);
			Type generatedType = emitter.BuildType();
			base.InitializeStaticFields(generatedType);
			return generatedType;
		}
Example #15
0
 public MixinContributor(INamingScope namingScope, bool canChangeTarget)
     : base(namingScope)
 {
     this.canChangeTarget = canChangeTarget;
     getTargetExpression = BuildGetTargetExpression();
 }
Example #16
0
 private EntityProxyNameScope(INamingScope parent)
 {
     this.parentScope = parent;
 }
		public DelegateProxyTargetContributor(Type targetType, INamingScope namingScope) : base(namingScope)
		{
			this.targetType = targetType;
		}
		protected override InterfaceProxyWithoutTargetContributor GetContributorForAdditionalInterfaces(
			INamingScope namingScope)
		{
			return new InterfaceProxyWithOptionalTargetContributor(namingScope, GetTargetExpression, GetTarget)
			{ Logger = Logger };
		}
Example #19
0
		/// <summary>
		///   Initializes a new instance of the <see cref = "ModuleScope" /> class, allowing to specify whether the assemblies generated by this instance
		///   should be saved and what simple names are to be assigned to them.
		/// </summary>
		/// <param name = "savePhysicalAssembly">If set to <c>true</c> saves the generated module.</param>
		/// <param name = "disableSignedModule">If set to <c>true</c> disables ability to generate signed module. This should be used in cases where ran under constrained permissions.</param>
		/// <param name = "namingScope">Naming scope used to provide unique names to generated types and their members (usually via sub-scopes).</param>
		/// <param name = "strongAssemblyName">The simple name of the strong-named assembly generated by this <see
		///    cref = "ModuleScope" />.</param>
		/// <param name = "strongModulePath">The path and file name of the manifest module of the strong-named assembly generated by this <see
		///    cref = "ModuleScope" />.</param>
		/// <param name = "weakAssemblyName">The simple name of the weak-named assembly generated by this <see cref = "ModuleScope" />.</param>
		/// <param name = "weakModulePath">The path and file name of the manifest module of the weak-named assembly generated by this <see
		///    cref = "ModuleScope" />.</param>
		public ModuleScope(bool savePhysicalAssembly, bool disableSignedModule, INamingScope namingScope,
						   string strongAssemblyName, string strongModulePath,
						   string weakAssemblyName, string weakModulePath)
		{
			this.savePhysicalAssembly = savePhysicalAssembly;
			this.disableSignedModule = disableSignedModule;
			this.namingScope = namingScope;
			this.strongAssemblyName = strongAssemblyName;
			this.strongModulePath = strongModulePath;
			this.weakAssemblyName = weakAssemblyName;
			this.weakModulePath = weakModulePath;

			this.internalsUtil = new InternalsUtil(this);
		}
Example #20
0
 private EntityProxyNameScope( INamingScope parent )
 {
     this.parentScope = parent;
 }
Example #21
0
 public ClassProxyTargetContributor(Type targetType, IList <MethodInfo> methodsToSkip, INamingScope namingScope)
     : base(namingScope)
 {
     this.targetType    = targetType;
     this.methodsToSkip = methodsToSkip;
 }
Example #22
0
        protected override ITypeContributor AddMappingForTargetType(
            IDictionary <Type, ITypeContributor> interfaceTypeImplementerMapping, Type proxyTargetType,
            ICollection <Type> targetInterfaces, ICollection <Type> additionalInterfaces, INamingScope namingScope)
        {
            var contributor = new InterfaceProxyWithoutTargetContributor(namingScope, Scope, (c, m) => NullExpression.Instance)
            {
                Logger = Logger
            };

            foreach (var @interface in targetType.GetAllInterfaces())
            {
                contributor.AddInterfaceToProxy(@interface);
                AddMappingNoCheck(@interface, contributor, interfaceTypeImplementerMapping);
            }
            return(contributor);
        }
 public InterfaceProxyTargetContributor(Type proxyTargetType, bool canChangeTarget, INamingScope namingScope)
     : base(namingScope)
 {
     this.proxyTargetType = proxyTargetType;
     this.canChangeTarget = canChangeTarget;
 }
Example #24
0
        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(MethodInfo));
                @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))
            {
                // Emit code to return with cast from ReturnValue

                // @mbrit - 2012-05-31 - see the note associated with the GetReturnValueForWinRt declaration
                // for more information on this...

                var useWinRtGenericHandler = false;
#if NETFX_CORE
                if (emitter.ReturnType == typeof(int) || emitter.ReturnType == typeof(bool))
                {
                    useWinRtGenericHandler = true;
                }
#endif
                if (!(useWinRtGenericHandler))
                {
                    var getRetVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue);
                    emitter.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(emitter.ReturnType, getRetVal)));
                }
                else
                {
#if NETFX_CORE
                    var grvArgs   = new Type[] { emitter.ReturnType };
                    var grvCall   = InvocationMethods.GetReturnValueForWinRt.MakeGenericMethod(grvArgs);
                    var getRetVal = new MethodInvocationExpression(invocationLocal, grvCall);
                    emitter.CodeBuilder.AddStatement(new ReturnStatement(getRetVal));
#endif
                }
            }
            else
            {
                emitter.CodeBuilder.AddStatement(new ReturnStatement());
            }

            return(emitter);
        }
Example #25
0
        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);
        }
Example #26
0
        protected FieldReference BuildMethodInterceptorsField(ClassEmitter @class, MethodInfo method, INamingScope namingScope)
        {
            var methodInterceptors = @class.CreateField(
                namingScope.GetUniqueName(string.Format("interceptors_{0}", method.Name)),
                typeof(IInterceptor[]),
                false);

#if !SILVERLIGHT
            @class.DefineCustomAttributeFor <XmlIgnoreAttribute>(methodInterceptors);
#endif
            return(methodInterceptors);
        }
Example #27
0
 private NamingScope(INamingScope parent)
 {
     parentScope = parent;
 }
 protected CompositeTypeContributor(INamingScope namingScope)
 {
     this.namingScope = namingScope;
 }
        private AbstractTypeEmitter GetEmitter(ClassEmitter @class, Type[] interfaces, INamingScope namingScope,
                                               MethodInfo methodInfo)
        {
            var suggestedName = string.Format("Castle.Proxies.Invocations.{0}_{1}", methodInfo.DeclaringType.Name,
                                              methodInfo.Name);
            var uniqueName = namingScope.ParentScope.GetUniqueName(suggestedName);

            return(new ClassEmitter(@class.ModuleScope, uniqueName, GetBaseType(), interfaces, ClassEmitter.DefaultAttributes, forceUnsigned: @class.InStrongNamedModule == false));
        }
Example #30
0
 public MixinContributor(INamingScope namingScope, bool canChangeTarget)
     : base(namingScope)
 {
     this.canChangeTarget = canChangeTarget;
     getTargetExpression  = BuildGetTargetExpression();
 }
		protected virtual InterfaceProxyWithoutTargetContributor GetContributorForAdditionalInterfaces(INamingScope namingScope)
		{
			return new InterfaceProxyWithoutTargetContributor(namingScope, (c, m) => NullExpression.Instance) { Logger = Logger };
		}
 public DelegateProxyTargetContributor(Type targetType, INamingScope namingScope) : base(namingScope)
 {
     this.targetType = targetType;
 }
Example #33
0
 protected abstract MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class,
                                                         INamingScope namingScope);
Example #34
0
 public InterfaceProxyWithoutTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget)
     : base(namingScope)
 {
     getTargetExpression = getTarget;
 }
        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);
        }
Example #36
0
        public AbstractTypeEmitter Generate(ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope)
        {
            var emitter = GetEmitter(@class, namingScope);

            BuildConstructor(emitter);
            BuildInvokeMethod(emitter);
            return(emitter);
        }
Example #37
0
 public InterfaceProxyWithTargetInterfaceTargetContributor(Type proxyTargetType, bool allowChangeTarget,
                                                           INamingScope namingScope)
     : base(proxyTargetType, allowChangeTarget, namingScope)
 {
 }
Example #38
0
        private Type GenerateType(string name, INamingScope namingScope)
        {
            IEnumerable <ITypeContributor> contributors;
            var implementedInterfaces = GetTypeImplementerMapping(out contributors, namingScope);

            var model = new MetaType();

            // Collect methods
            foreach (var contributor in contributors)
            {
                contributor.CollectElementsToProxy(ProxyGenerationOptions.Hook, model);
            }
            ProxyGenerationOptions.Hook.MethodsInspected();

            var emitter = BuildClassEmitter(name, targetType, implementedInterfaces);

            CreateFields(emitter);
            CreateTypeAttributes(emitter);

            // Constructor
            var cctor = GenerateStaticConstructor(emitter);

            var targetField          = CreateTargetField(emitter);
            var constructorArguments = new List <FieldReference> {
                targetField
            };

            foreach (var contributor in contributors)
            {
                contributor.Generate(emitter, ProxyGenerationOptions);

                // TODO: redo it
                if (contributor is MixinContributor)
                {
                    constructorArguments.AddRange((contributor as MixinContributor).Fields);
                }
            }

            // constructor arguments
            var interceptorsField = emitter.GetField("__interceptors");

            constructorArguments.Add(interceptorsField);
            var selector = emitter.GetField("__selector");

            if (selector != null)
            {
                constructorArguments.Add(selector);
            }

            GenerateConstructors(emitter, targetType, constructorArguments.ToArray());
            GenerateParameterlessConstructor(emitter, targetType, interceptorsField);

            // Complete type initializer code body
            CompleteInitCacheMethod(cctor.CodeBuilder);

            // Crosses fingers and build type

            var proxyType = emitter.BuildType();

            InitializeStaticFields(proxyType);
            return(proxyType);
        }
		protected CompositeTypeContributor(INamingScope namingScope)
		{
			this.namingScope = namingScope;
		}
Example #40
0
        protected virtual IEnumerable <Type> GetTypeImplementerMapping(out IEnumerable <ITypeContributor> contributors,
                                                                       INamingScope namingScope)
        {
            var methodsToSkip = new List <MethodInfo>();
            var proxyInstance = new ClassProxyInstanceContributor(targetType, methodsToSkip, additionalInterfacesToProxy,
                                                                  ProxyTypeConstants.ClassWithTarget);
            // TODO: the trick with methodsToSkip is not very nice...
            var proxyTarget = new ClassProxyWithTargetTargetContributor(targetType, methodsToSkip, namingScope)
            {
                Logger = Logger
            };
            IDictionary <Type, ITypeContributor> typeImplementerMapping = new Dictionary <Type, ITypeContributor>();

            // Order of interface precedence:
            // 1. first target
            // target is not an interface so we do nothing

            var targetInterfaces = targetType.GetAllInterfaces();
            // 2. then mixins
            var mixins = new MixinContributor(namingScope, false)
            {
                Logger = Logger
            };

            if (ProxyGenerationOptions.HasMixins)
            {
                foreach (var mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfaces)
                {
                    if (targetInterfaces.Contains(mixinInterface))
                    {
                        // OK, so the target implements this interface. We now do one of two things:
                        if (additionalInterfacesToProxy.Contains(mixinInterface) &&
                            typeImplementerMapping.ContainsKey(mixinInterface) == false)
                        {
                            AddMappingNoCheck(mixinInterface, proxyTarget, typeImplementerMapping);
                            proxyTarget.AddInterfaceToProxy(mixinInterface);
                        }
                        // we do not intercept the interface
                        mixins.AddEmptyInterface(mixinInterface);
                    }
                    else
                    {
                        if (!typeImplementerMapping.ContainsKey(mixinInterface))
                        {
                            mixins.AddInterfaceToProxy(mixinInterface);
                            AddMappingNoCheck(mixinInterface, mixins, typeImplementerMapping);
                        }
                    }
                }
            }
            var additionalInterfacesContributor = new InterfaceProxyWithoutTargetContributor(namingScope,
                                                                                             (c, m) => NullExpression.Instance)
            {
                Logger = Logger
            };

            // 3. then additional interfaces
            foreach (var @interface in additionalInterfacesToProxy)
            {
                if (targetInterfaces.Contains(@interface))
                {
                    if (typeImplementerMapping.ContainsKey(@interface))
                    {
                        continue;
                    }

                    // we intercept the interface, and forward calls to the target type
                    AddMappingNoCheck(@interface, proxyTarget, typeImplementerMapping);
                    proxyTarget.AddInterfaceToProxy(@interface);
                }
                else if (ProxyGenerationOptions.MixinData.ContainsMixin(@interface) == false)
                {
                    additionalInterfacesContributor.AddInterfaceToProxy(@interface);
                    AddMapping(@interface, additionalInterfacesContributor, typeImplementerMapping);
                }
            }
#if !SILVERLIGHT
            // 4. plus special interfaces
            if (targetType.IsSerializable)
            {
                AddMappingForISerializable(typeImplementerMapping, proxyInstance);
            }
#endif
            try
            {
                AddMappingNoCheck(typeof(IProxyTargetAccessor), proxyInstance, typeImplementerMapping);
            }
            catch (ArgumentException)
            {
                HandleExplicitlyPassedProxyTargetAccessor(targetInterfaces, additionalInterfacesToProxy);
            }

            contributors = new List <ITypeContributor>
            {
                proxyTarget,
                mixins,
                additionalInterfacesContributor,
                proxyInstance
            };
            return(typeImplementerMapping.Keys);
        }
        public virtual void Generate(ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope)
        {
            foreach (var method in methods)
            {
                if (!method.Standalone)
                {
                    continue;
                }

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

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

            foreach (var @event in events)
            {
                ImplementEvent(@class, @event, options, namingScope);
            }
        }
        public InterfaceProxyTargetContributor(Type proxyTargetType, bool canChangeTarget, INamingScope namingScope, ModuleScope scope)
			: base(namingScope, scope)
		{
			this.proxyTargetType = proxyTargetType;
			this.canChangeTarget = canChangeTarget;
		}
 public override void Generate(ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope)
 {
     if (constructorContributor != null && registrar != null)
     {
         foreach (var statement in registrar.ConstructorStatements)
         {
             constructorContributor.AppendConstructorStatement(statement);
         }
     }
     base.Generate(@class, options, namingScope);
 }
        protected override ITypeContributor AddMappingForTargetType(IDictionary <Type, ITypeContributor> typeImplementerMapping, Type proxyTargetType, ICollection <Type> targetInterfaces, ICollection <Type> additionalInterfaces, INamingScope namingScope)
        {
            var contributor = new InterfaceProxyWithTargetInterfaceTargetContributor(
                proxyTargetType,
                AllowChangeTarget,
                namingScope)
            {
                Logger = Logger
            };

            foreach (var @interface in targetType.GetAllInterfaces())
            {
                contributor.AddInterfaceToProxy(@interface);
                AddMappingNoCheck(@interface, contributor, typeImplementerMapping);
            }

            return(contributor);
        }
		private Expression SetMethodInterceptors(ClassEmitter @class, INamingScope namingScope, MethodEmitter emitter, Expression proxiedMethodTokenExpression)
		{
			var selector = @class.GetField("__selector");
			if(selector == null)
			{
				return null;
			}


			var methodInterceptorsField = BuildMethodInterceptorsField(@class, MethodToOverride, namingScope);

			var emptyInterceptors = new NewArrayExpression(0, typeof(IInterceptor));
			var selectInterceptors = new MethodInvocationExpression(selector, InterceptorSelectorMethods.SelectInterceptors,
			                                                        new MethodInvocationExpression(null,
				                                                        TypeUtilMethods.GetTypeOrNull,
				                                                        getTargetExpression(@class, MethodToOverride)),
			                                                        proxiedMethodTokenExpression, interceptors.ToExpression())
			{ VirtualCall = true };

			emitter.CodeBuilder.AddExpression(
				new IfNullExpression(methodInterceptorsField,
				                     new AssignStatement(methodInterceptorsField,
				                                         new NullCoalescingOperatorExpression(selectInterceptors, emptyInterceptors))));

			return methodInterceptorsField.ToExpression();
		}
 protected CompositeTypeContributor(INamingScope namingScope, ModuleScope scope)
 {
     this.scope = scope;
     this.namingScope = namingScope;
 }
		protected virtual IEnumerable<Type> GetTypeImplementerMapping(Type[] interfaces, Type proxyTargetType, out IEnumerable<ITypeContributor> contributors, INamingScope namingScope)
		{
			IDictionary<Type, ITypeContributor> typeImplementerMapping = new Dictionary<Type, ITypeContributor>();
			var mixins = new MixinContributor(namingScope, AllowChangeTarget) { Logger = Logger };
			// Order of interface precedence:
			// 1. first target
			ICollection<Type> targetInterfaces = proxyTargetType.GetAllInterfaces();
			ICollection<Type> additionalInterfaces = TypeUtil.GetAllInterfaces(interfaces);
			var target = AddMappingForTargetType(typeImplementerMapping, proxyTargetType, targetInterfaces, additionalInterfaces,namingScope);

			// 2. then mixins
			if (ProxyGenerationOptions.HasMixins)
			{
				foreach (var mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfaces)
				{
					if (targetInterfaces.Contains(mixinInterface))
					{
						// OK, so the target implements this interface. We now do one of two things:
						if(additionalInterfaces.Contains(mixinInterface))
						{
							// we intercept the interface, and forward calls to the target type
							AddMapping(mixinInterface, target, typeImplementerMapping);
						}
						// we do not intercept the interface
						mixins.AddEmptyInterface(mixinInterface);
					}
					else
					{
						if (!typeImplementerMapping.ContainsKey(mixinInterface))
						{
							mixins.AddInterfaceToProxy(mixinInterface);
							typeImplementerMapping.Add(mixinInterface, mixins);
						}
					}
				}
			}

			var additionalInterfacesContributor = GetContributorForAdditionalInterfaces(namingScope);
			// 3. then additional interfaces
			foreach (var @interface in additionalInterfaces)
			{
				if(typeImplementerMapping.ContainsKey(@interface)) continue;
				if(ProxyGenerationOptions.MixinData.ContainsMixin(@interface)) continue;

				additionalInterfacesContributor.AddInterfaceToProxy(@interface);
				AddMappingNoCheck(@interface, additionalInterfacesContributor, typeImplementerMapping);
			}

			// 4. plus special interfaces
			var instance = new InterfaceProxyInstanceContributor(targetType, GeneratorType, interfaces);
			AddMappingForISerializable(typeImplementerMapping, instance);
			try
			{
				AddMappingNoCheck(typeof(IProxyTargetAccessor), instance, typeImplementerMapping);
			}
			catch (ArgumentException)
			{
				HandleExplicitlyPassedProxyTargetAccessor(targetInterfaces, additionalInterfaces);
			}

			contributors = new List<ITypeContributor>
			{
				target,
				additionalInterfacesContributor,
				mixins,
				instance
			};
			return typeImplementerMapping.Keys;
		}
		private Expression[] GetCtorArguments(ClassEmitter @class, INamingScope namingScope, Expression proxiedMethodTokenExpression, TypeReference[] dereferencedArguments)
		{
			var selector = @class.GetField("__selector");
			if (selector != null)
			{
				return new[]
				{
					getTargetExpression(@class, MethodToOverride),
					SelfReference.Self.ToExpression(),
					interceptors.ToExpression(),
					proxiedMethodTokenExpression,
					new ReferencesToObjectArrayExpression(dereferencedArguments),
					selector.ToExpression(),
					new AddressOfReferenceExpression(BuildMethodInterceptorsField(@class, MethodToOverride, namingScope))
				};
			}
			return new[]
			{
				getTargetExpression(@class, MethodToOverride),
				SelfReference.Self.ToExpression(),
				interceptors.ToExpression(),
				proxiedMethodTokenExpression,
				new ReferencesToObjectArrayExpression(dereferencedArguments)
			};
		}
Example #49
0
		protected virtual IEnumerable<Type> GetTypeImplementerMapping(Type[] interfaces,
		                                                              out IEnumerable<ITypeContributor> contributors,
		                                                              INamingScope namingScope)
		{
			var methodsToSkip = new List<MethodInfo>();
			var proxyInstance = new ClassProxyInstanceContributor(targetType, methodsToSkip, interfaces, ProxyTypeConstants.Class);
			// TODO: the trick with methodsToSkip is not very nice...
			var proxyTarget = new ClassProxyTargetContributor(targetType, methodsToSkip, namingScope) { Logger = Logger };
			IDictionary<Type, ITypeContributor> typeImplementerMapping = new Dictionary<Type, ITypeContributor>();

			// Order of interface precedence:
			// 1. first target
			// target is not an interface so we do nothing

			var targetInterfaces = targetType.GetAllInterfaces();
			var additionalInterfaces = TypeUtil.GetAllInterfaces(interfaces);
			// 2. then mixins
			var mixins = new MixinContributor(namingScope, false) { Logger = Logger };
			if (ProxyGenerationOptions.HasMixins)
			{
				foreach (var mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfaces)
				{
					if (targetInterfaces.Contains(mixinInterface))
					{
						// OK, so the target implements this interface. We now do one of two things:
						if (additionalInterfaces.Contains(mixinInterface) && typeImplementerMapping.ContainsKey(mixinInterface) == false)
						{
							AddMappingNoCheck(mixinInterface, proxyTarget, typeImplementerMapping);
							proxyTarget.AddInterfaceToProxy(mixinInterface);
						}
						// we do not intercept the interface
						mixins.AddEmptyInterface(mixinInterface);
					}
					else
					{
						if (!typeImplementerMapping.ContainsKey(mixinInterface))
						{
							mixins.AddInterfaceToProxy(mixinInterface);
							AddMappingNoCheck(mixinInterface, mixins, typeImplementerMapping);
						}
					}
				}
			}
			var additionalInterfacesContributor = new InterfaceProxyWithoutTargetContributor(namingScope,
			                                                                                 (c, m) => NullExpression.Instance)
			{ Logger = Logger };
			// 3. then additional interfaces
			foreach (var @interface in additionalInterfaces)
			{
				if (targetInterfaces.Contains(@interface))
				{
					if (typeImplementerMapping.ContainsKey(@interface))
					{
						continue;
					}

					// we intercept the interface, and forward calls to the target type
					AddMappingNoCheck(@interface, proxyTarget, typeImplementerMapping);
					proxyTarget.AddInterfaceToProxy(@interface);
				}
				else if (ProxyGenerationOptions.MixinData.ContainsMixin(@interface) == false)
				{
					additionalInterfacesContributor.AddInterfaceToProxy(@interface);
					AddMapping(@interface, additionalInterfacesContributor, typeImplementerMapping);
				}
			}
			// 4. plus special interfaces
#if FEATURE_SERIALIZATION
			if (targetType.IsSerializable)
			{
				AddMappingForISerializable(typeImplementerMapping, proxyInstance);
			}
#endif
			try
			{
				AddMappingNoCheck(typeof(IProxyTargetAccessor), proxyInstance, typeImplementerMapping);
			}
			catch (ArgumentException)
			{
				HandleExplicitlyPassedProxyTargetAccessor(targetInterfaces, additionalInterfaces);
			}

			contributors = new List<ITypeContributor>
			{
				proxyTarget,
				mixins,
				additionalInterfacesContributor,
				proxyInstance
			};
			return typeImplementerMapping.Keys;
		}
 protected override InterfaceProxyWithoutTargetContributor GetContributorForAdditionalInterfaces(INamingScope namingScope)
 {
     return(new InterfaceProxyWithOptionalTargetContributor(namingScope, GetTargetExpression, GetTarget)
     {
         Logger = Logger
     });
 }
		public InterfaceProxyWithTargetInterfaceTargetContributor(Type proxyTargetType, bool allowChangeTarget,
                                                                  INamingScope namingScope, ModuleScope scope)
			: base(proxyTargetType, allowChangeTarget, namingScope, scope)
		{
		}
Example #52
0
        /// <summary>
        /// Gets the contributors for generating the type definition.
        /// </summary>
        /// <param name="interfaces">Additional interfaces to implement.</param>
        /// <param name="proxyTargetType">The target type for the proxy.</param>
        /// <param name="contributors">The list of contributors that will be used to generate the type.</param>
        /// <param name="namingScope">The proxy type naming scope.</param>
        /// <returns>
        /// The list of types being implemented.
        /// </returns>
        /// <remarks>
        /// <para>
        /// This version of the method basically does the same thing as the
        /// original/base implementation but with these key differences:
        /// </para>
        /// <list type="bullet">
        /// <item>
        /// <term>No mixin support</term>
        /// <description>
        /// The original version of the method looks at the <see cref="Castle.DynamicProxy.Generators.BaseProxyGenerator.ProxyGenerationOptions"/>
        /// to see if there are any mixins to be added to the generated proxy.
        /// There is no need for mixin support in WCF service hosting so mixins
        /// aren't even checked for and won't be added.
        /// </description>
        /// </item>
        /// <item>
        /// <term>No additional interfaces</term>
        /// <description>
        /// The original version of the method goes through each of the additional
        /// interfaces that the are to be implemented, checks them against collisions
        /// with mixin definitions, and adds type mappings for the additional interfaces.
        /// The only interface that needs to be implemented for the WCF hosting
        /// proxy is the service interface, so all of that additional interface
        /// checking is skipped.
        /// </description>
        /// </item>
        /// <item>
        /// <term>Custom instance contributor used</term>
        /// <description>
        /// The original version of the method uses the
        /// <see cref="Castle.DynamicProxy.Contributors.InterfaceProxyInstanceContributor"/>
        /// as the code generator for the proxy type. Unfortunately, that contributor
        /// copies over all non-inherited attributes on the interface including
        /// the <see cref="System.ServiceModel.ServiceContractAttribute"/>. The
        /// concrete proxy type can't have that attribute because the interface
        /// already has it, so WCF hosting dies. This version of the method uses
        /// the <see cref="Autofac.Multitenant.Wcf.DynamicProxy.IgnoreAttributeInterfaceProxyInstanceContributor"/>
        /// which does not copy over non-inherited attributes.
        /// </description>
        /// </item>
        /// </list>
        /// </remarks>
        /// <seealso cref="Autofac.Multitenant.Wcf.DynamicProxy.IgnoreAttributeInterfaceProxyInstanceContributor"/>
        protected override IEnumerable <Type> GetTypeImplementerMapping(Type[] interfaces, Type proxyTargetType, out IEnumerable <ITypeContributor> contributors, INamingScope namingScope)
        {
            var typeImplementerMapping = new Dictionary <Type, ITypeContributor>();
            var allInterfaces          = TypeUtil.GetAllInterfaces(new[] { proxyTargetType });
            var additionalInterfaces   = TypeUtil.GetAllInterfaces(interfaces);
            var implementer            = AddMappingForTargetType(typeImplementerMapping, proxyTargetType, allInterfaces, additionalInterfaces, namingScope);
            var instance = new IgnoreAttributeInterfaceProxyInstanceContributor(targetType, GeneratorType, interfaces);

            AddMappingForISerializable(typeImplementerMapping, instance);
            try
            {
                AddMappingNoCheck(typeof(IProxyTargetAccessor), instance, typeImplementerMapping);
            }
            catch (ArgumentException)
            {
                HandleExplicitlyPassedProxyTargetAccessor(allInterfaces, additionalInterfaces);
            }
            contributors = new List <ITypeContributor> {
                implementer, instance
            };
            return(typeImplementerMapping.Keys);
        }
 protected CompositeTypeContributor(INamingScope namingScope, ModuleScope scope)
 {
     this.scope       = scope;
     this.namingScope = namingScope;
 }
Example #54
0
        private AbstractTypeEmitter GetEmitter(ClassEmitter @class, Type[] interfaces, INamingScope namingScope,
                                               MethodInfo methodInfo)
        {
            var suggestedName = string.Format("Hermit.Proxies.Invocations.{0}_{1}", methodInfo.DeclaringType.Name,
                                              methodInfo.Name);
            var uniqueName = namingScope.ParentScope.GetUniqueName(suggestedName);

            return(new ClassEmitter(@class.ModuleScope, uniqueName, GetBaseType(), interfaces));
        }
		protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options,INamingScope namingScope)
		{
			var invocationType = invocation;

			Trace.Assert(MethodToOverride.IsGenericMethod == invocationType.IsGenericTypeDefinition);
			Type[] genericMethodArgs = Type.EmptyTypes;

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


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

				// Not in the cache: generic method
				proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericMethodArgs));
			}
			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 dereferencedArguments = IndirectReference.WrapIfByRef(emitter.Arguments);


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

			var invocationLocal = emitter.CodeBuilder.DeclareLocal(invocationType);
			emitter.CodeBuilder.AddStatement(new AssignStatement(invocationLocal,
			                                                     new NewInstanceExpression(constructor, ctorArguments)));

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

			emitter.CodeBuilder.AddStatement(
				new ExpressionStatement(new MethodInvocationExpression(invocationLocal, InvocationMethods.Proceed)));

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

			if (MethodToOverride.ReturnType != typeof(void))
			{
				// Emit code to return with cast from ReturnValue
				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;
		}
Example #56
0
        public AbstractTypeEmitter Generate(ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope)
        {
            var methodInfo = method.Method;

            var interfaces = new Type[0];

            if (canChangeTarget)
            {
                interfaces = new[] { typeof(IChangeProxyTarget) };
            }
            var invocation = GetEmitter(@class, interfaces, namingScope, methodInfo);

            // invocation only needs to mirror the generic parameters of the MethodInfo
            // targetType cannot be a generic type definition (YET!)
            invocation.CopyGenericParametersFromMethod(methodInfo);

            CreateConstructor(invocation, options);

            var targetField = GetTargetReference();

            if (canChangeTarget)
            {
                ImplementChangeProxyTargetInterface(@class, invocation, targetField);
            }

            ImplemementInvokeMethodOnTarget(invocation, methodInfo.GetParameters(), targetField, callback);

            invocation.DefineCustomAttribute <SerializableAttribute>();

            return(invocation);
        }
        protected virtual IEnumerable <Type> GetTypeImplementerMapping(Type[] interfaces, Type proxyTargetType,
                                                                       out IEnumerable <ITypeContributor> contributors,
                                                                       INamingScope namingScope)
        {
            IDictionary <Type, ITypeContributor> typeImplementerMapping = new Dictionary <Type, ITypeContributor>();
            var mixins = new MixinContributor(namingScope, AllowChangeTarget)
            {
                Logger = Logger
            };
            // Order of interface precedence:
            // 1. first target
            var targetInterfaces     = proxyTargetType.GetAllInterfaces();
            var additionalInterfaces = TypeUtil.GetAllInterfaces(interfaces);
            var target = AddMappingForTargetType(typeImplementerMapping, proxyTargetType, targetInterfaces, additionalInterfaces,
                                                 namingScope);

            // 2. then mixins
            if (ProxyGenerationOptions.HasMixins)
            {
                foreach (var mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfaces)
                {
                    if (targetInterfaces.Contains(mixinInterface))
                    {
                        // OK, so the target implements this interface. We now do one of two things:
                        if (additionalInterfaces.Contains(mixinInterface))
                        {
                            // we intercept the interface, and forward calls to the target type
                            AddMapping(mixinInterface, target, typeImplementerMapping);
                        }
                        // we do not intercept the interface
                        mixins.AddEmptyInterface(mixinInterface);
                    }
                    else
                    {
                        if (!typeImplementerMapping.ContainsKey(mixinInterface))
                        {
                            mixins.AddInterfaceToProxy(mixinInterface);
                            typeImplementerMapping.Add(mixinInterface, mixins);
                        }
                    }
                }
            }

            var additionalInterfacesContributor = GetContributorForAdditionalInterfaces(namingScope);

            // 3. then additional interfaces
            foreach (var @interface in additionalInterfaces)
            {
                if (typeImplementerMapping.ContainsKey(@interface))
                {
                    continue;
                }
                if (ProxyGenerationOptions.MixinData.ContainsMixin(@interface))
                {
                    continue;
                }

                additionalInterfacesContributor.AddInterfaceToProxy(@interface);
                AddMappingNoCheck(@interface, additionalInterfacesContributor, typeImplementerMapping);
            }

            // 4. plus special interfaces
            var instance = new InterfaceProxyInstanceContributor(targetType, GeneratorType, interfaces);

#if FEATURE_SERIALIZATION
            AddMappingForISerializable(typeImplementerMapping, instance);
#endif
            try
            {
                AddMappingNoCheck(typeof(IProxyTargetAccessor), instance, typeImplementerMapping);
            }
            catch (ArgumentException)
            {
                HandleExplicitlyPassedProxyTargetAccessor(targetInterfaces, additionalInterfaces);
            }

            contributors = new List <ITypeContributor>
            {
                target,
                additionalInterfacesContributor,
                mixins,
                instance
            };
            return(typeImplementerMapping.Keys);
        }
Example #58
0
        protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, INamingScope namingScope)
        {
            var invocationType = invocation;

            var genericArguments = Type.EmptyTypes;

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

            IExpression proxiedMethodTokenExpression;

            if (MethodToOverride.IsGenericMethod)
            {
                // Not in the cache: generic method
                genericArguments             = emitter.MethodBuilder.GetGenericArguments();
                proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericArguments));

                if (invocationType.IsGenericTypeDefinition)
                {
                    // bind generic method arguments to invocation's type arguments
                    invocationType = invocationType.MakeGenericType(genericArguments);
                    constructor    = TypeBuilder.GetConstructor(invocationType, constructor);
                }
            }
            else
            {
                var proxiedMethodToken = @class.CreateStaticField(namingScope.GetUniqueName("token_" + MethodToOverride.Name), typeof(MethodInfo));
                @class.ClassConstructor.CodeBuilder.AddStatement(new AssignStatement(proxiedMethodToken, new MethodTokenExpression(MethodToOverride)));

                proxiedMethodTokenExpression = proxiedMethodToken;
            }

            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)
            {
                EmitLoadGenericMethodArguments(emitter, MethodToOverride.MakeGenericMethod(genericArguments), invocationLocal);
            }

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

            var proceed = 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.AddStatement(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);
        }
		public InterfaceProxyWithoutTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget)
			: base(namingScope)
		{
			getTargetExpression = getTarget;
		}
        protected virtual Type GenerateType(string typeName, Type proxyTargetType, Type[] interfaces, INamingScope namingScope)
        {
            var allInterfaces = GetTypeImplementerMapping(interfaces, proxyTargetType, out IEnumerable <ITypeContributor> contributors, namingScope);

            var baseType = Init(typeName, out ClassEmitter emitter, proxyTargetType, out FieldReference interceptorsField, allInterfaces);

            var model = new MetaType();

            // Collect methods
            foreach (var contributor in contributors)
            {
                contributor.CollectElementsToProxy(ProxyGenerationOptions.Hook, model);
            }

            ProxyGenerationOptions.Hook.MethodsInspected();

            // Constructor

            var cctor         = GenerateStaticConstructor(emitter);
            var ctorArguments = new List <FieldReference>();

            foreach (var contributor in contributors)
            {
                contributor.Generate(emitter, ProxyGenerationOptions);

                // TODO: redo it
                if (contributor is MixinContributor)
                {
                    ctorArguments.AddRange((contributor as MixinContributor).Fields);
                }
            }

            ctorArguments.Add(interceptorsField);
            ctorArguments.Add(targetField);
            var selector = emitter.GetField("__selector");

            if (selector != null)
            {
                ctorArguments.Add(selector);
            }

            GenerateConstructors(emitter, baseType, ctorArguments.ToArray());

            // Complete type initializer code body
            CompleteInitCacheMethod(cctor.CodeBuilder);

            // Crosses fingers and build type
            var generatedType = emitter.BuildType();

            InitializeStaticFields(generatedType);
            return(generatedType);
        }