protected override ArgumentReference[] GetCtorArgumentsAndBaseCtorToCall(Type targetFieldType, ProxyGenerationOptions proxyGenerationOptions,out ConstructorInfo baseConstructor)
		{
			if (proxyGenerationOptions.Selector == null)
			{
				baseConstructor = InvocationMethods.CompositionInvocationConstructorNoSelector;
				return new[]
				{
					new ArgumentReference(targetFieldType),
					new ArgumentReference(typeof(object)),
					new ArgumentReference(typeof(IInterceptor[])),
					new ArgumentReference(typeof(MethodInfo)),
					new ArgumentReference(typeof(object[])),
				};
			}

			baseConstructor = InvocationMethods.CompositionInvocationConstructorWithSelector;
			return new[]
			{
				new ArgumentReference(targetFieldType),
				new ArgumentReference(typeof(object)),
				new ArgumentReference(typeof(IInterceptor[])),
				new ArgumentReference(typeof(MethodInfo)),
				new ArgumentReference(typeof(object[])),
				new ArgumentReference(typeof(IInterceptorSelector)),
				new ArgumentReference(typeof(IInterceptor[]).MakeByRefType())
			};
		}
예제 #2
0
		/// <summary>
		/// Returns a proxy capable of field interception.
		/// </summary>
		/// <returns></returns>
        public override object GetFieldInterceptionProxy() 
        {
            var proxyGenerationOptions = new ProxyGenerationOptions();
            var interceptor = new LazyFieldInterceptor();
            proxyGenerationOptions.AddMixinInstance(interceptor);
            return ProxyGenerator.CreateClassProxy(PersistentClass, proxyGenerationOptions, interceptor);
        }
		public virtual void Generate(ClassEmitter @class, ProxyGenerationOptions options)
		{
			foreach (var method in methods)
			{
				if (!method.Standalone)
				{
					continue;
				}

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

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

			foreach (var @event in events)
			{
				ImplementEvent(@class, @event, options);
			}
		}
예제 #4
0
		/// <summary>
		///   Initializes a new instance of the <see cref = "CacheKey" /> class.
		/// </summary>
		/// <param name = "target">Target element. This is either target type or target method for invocation types.</param>
		/// <param name = "type">The type of the proxy. This is base type for invocation types.</param>
		/// <param name = "interfaces">The interfaces.</param>
		/// <param name = "options">The options.</param>
		public CacheKey(MemberInfo target, Type type, Type[] interfaces, ProxyGenerationOptions options)
		{
			this.target = target;
			this.type = type;
			this.interfaces = interfaces ?? Type.EmptyTypes;
			this.options = options;
		}
예제 #5
0
		/// <summary>
		///   Initializes a new instance of the <see cref = "CacheKey" /> class.
		/// </summary>
		/// <param name = "target">Target element. This is either target type or target method for invocation types.</param>
		/// <param name = "type">The type of the proxy. This is base type for invocation types.</param>
		/// <param name = "interfaces">The interfaces.</param>
		/// <param name = "options">The options.</param>
		private CacheKey(MemberWrapper target, Type type, Type[] interfaces, ProxyGenerationOptions options)
		{
			this.target = target;
			this.type = type;
			this.interfaces = interfaces ?? TypeExtender.EmptyTypes;
			this.options = options;
		}
		private Type GetInvocationType(MetaMethod method, ClassEmitter @class, ProxyGenerationOptions options)
		{
			var scope = @class.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(@class, options, namingScope).BuildType();

			scope.RegisterInCache(key, invocation);

			return invocation;
		}
		protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class,
		                                                      ProxyGenerationOptions options,
		                                                      OverrideMethodDelegate overrideMethod)
		{
			if (methodsToSkip.Contains(method.Method))
				return null;

			if (!method.Proxyable)
			{
				return new MinimialisticMethodGenerator(method,
				                                        overrideMethod);
			}

			if (ExplicitlyImplementedInterfaceMethod(method))
			{
#if SILVERLIGHT
				return null;
#else
				return ExplicitlyImplementedInterfaceMethodGenerator(method, @class, options, overrideMethod);
#endif
			}

			var invocation = GetInvocationType(method, @class, options);

			return new MethodWithInvocationGenerator(method,
			                                         @class.GetField("__interceptors"),
			                                         invocation,
			                                         (c, m) => new TypeTokenExpression(targetType),
			                                         overrideMethod,
			                                         null);
		}
		protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class,
		                                                      ProxyGenerationOptions options,
		                                                      OverrideMethodDelegate overrideMethod)
		{
			if (methodsToSkip.Contains(method.Method))
			{
				return null;
			}

			if (!method.Proxyable)
			{
				return new MinimialisticMethodGenerator(method,
				                                        overrideMethod);
			}

			if (IsDirectlyAccessible(method) == false)
			{
				return IndirectlyCalledMethodGenerator(method, @class, options, overrideMethod);
			}

			var invocation = GetInvocationType(method, @class, options);

			return new MethodWithInvocationGenerator(method,
			                                         @class.GetField("__interceptors"),
			                                         invocation,
			                                         (c, m) => c.GetField("__target").ToExpression(),
			                                         overrideMethod,
			                                         null);
		}
		protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class,
		                                                      ProxyGenerationOptions options,
		                                                      OverrideMethodDelegate overrideMethod)
		{
			if (!method.Proxyable)
			{
				return new ForwardingMethodGenerator(method,
				                                     overrideMethod,
				                                     (c, m) => c.GetField("__target"));
			}

			var targetMethod = options.ProxyEffectiveType == null ? method.Method : InvocationHelper.GetMethodOnType(proxyTargetType, method.Method);

			if (targetMethod == null)
			{
				return new MinimialisticMethodGenerator(method, overrideMethod);
			}

			var invocation = GetInvocationType(method, targetMethod, @class, options);

			return new MethodWithInvocationGenerator(method,
			                                         @class.GetField("__interceptors"),
			                                         invocation,
			                                         (c, m) => c.GetField("__target").ToExpression(),
			                                         overrideMethod,
			                                         null);
		}
예제 #10
0
		protected void SetGenerationOptions (ProxyGenerationOptions options)
		{
			if (proxyGenerationOptions != null)
			{
				throw new InvalidOperationException ("ProxyGenerationOptions can only be set once.");
			}
			proxyGenerationOptions = options;
		}
		public virtual void Generate(ClassEmitter @class, ProxyGenerationOptions options)
		{
			var interceptors = @class.GetField("__interceptors");
			ImplementProxyTargetAccessor(@class, interceptors);
			foreach (var attribute in targetType.GetNonInheritableAttributes())
			{
				@class.DefineCustomAttribute(attribute);
			}
		}
		public void On_interfaces()
		{
			var options = new ProxyGenerationOptions();
			options.AdditionalAttributes.Add(AttributeUtil.CreateInfo<__Protect>());

			var proxy = generator.CreateInterfaceProxyWithoutTarget(typeof(IDisposable), new Type[0], options);

			Assert.IsTrue(proxy.GetType().GetTypeInfo().IsDefined(typeof(__Protect), false));
		}
예제 #13
0
		protected void SetGenerationOptions (ProxyGenerationOptions options, ClassEmitter emitter)
		{
			if (proxyGenerationOptions != null)
			{
				throw new InvalidOperationException ("ProxyGenerationOptions can only be set once.");
			}
			proxyGenerationOptions = options;
			proxyGenerationOptionsField = emitter.CreateStaticField ("proxyGenerationOptions", typeof (ProxyGenerationOptions));
		}
		public void On_interfaces()
		{
			ProxyGenerationOptions options = new ProxyGenerationOptions();
			options.AttributesToAddToGeneratedTypes.Add(new __Protect());
		
			object proxy = new ProxyGenerator().CreateInterfaceProxyWithoutTarget(typeof(IDisposable), new Type[0], options);

			Assert.IsTrue(proxy.GetType().IsDefined(typeof(__Protect), false));
		}
		public void On_class()
		{
			ProxyGenerationOptions options = new ProxyGenerationOptions();
			options.AttributesToAddToGeneratedTypes.Add(new __Protect());

			object proxy = new ProxyGenerator().CreateClassProxy(typeof(CanDefineAdditionalCustomAttributes), options);

			Assert.IsTrue(proxy.GetType().IsDefined(typeof(__Protect), false));
		}
		public void On_class()
		{
			var options = new ProxyGenerationOptions();
			options.AdditionalAttributes.Add(AttributeUtil.CreateInfo<__Protect>());

			var proxy = generator.CreateClassProxy(typeof(CanDefineAdditionalCustomAttributes), options);

			Assert.IsTrue(proxy.GetType().GetTypeInfo().IsDefined(typeof(__Protect), false));
		}
		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;
		}
		public void Mixin_methods_should_be_forwarded_to_target_if_implements_mixin_interface()
		{
			var options = new ProxyGenerationOptions();
			options.AddMixinInstance(new Two());
			var proxy = generator.CreateInterfaceProxyWithTargetInterface(typeof(IOne),
			                                                              new OneTwo(),
			                                                              options);
			var result = (proxy as ITwo).TwoMethod();
			Assert.AreEqual(2, result);
		}
        protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class,
                                                              ProxyGenerationOptions options,
                                                              OverrideMethodDelegate overrideMethod)
        {
            if (!method.Proxyable)
            {
                return new OptionallyForwardingMethodGenerator(method, overrideMethod, getTargetReference);
            }

            return base.GetMethodGenerator(method, @class, options, overrideMethod);
        }
예제 #20
0
		public Type GenerateCode(Type[] interfaces, ProxyGenerationOptions options)
		{
			// make sure ProxyGenerationOptions is initialized
			options.Initialize();

			interfaces = TypeUtil.GetAllInterfaces(interfaces);
			CheckNotGenericTypeDefinitions(interfaces, "interfaces");
			ProxyGenerationOptions = options;
			var cacheKey = new CacheKey(targetType, interfaces, options);
			return ObtainProxyType(cacheKey, (n, s) => GenerateType(n, interfaces, s));
		}
		public ClassProxyWithTargetGenerator(ModuleScope scope, Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
			: base(scope, classToProxy)
		{
			CheckNotGenericTypeDefinition(targetType, "targetType");
			EnsureDoesNotImplementIProxyTargetAccessor(targetType, "targetType");
			CheckNotGenericTypeDefinitions(additionalInterfacesToProxy, "additionalInterfacesToProxy");

			options.Initialize();
			ProxyGenerationOptions = options;
			this.additionalInterfacesToProxy = TypeUtil.GetAllInterfaces(additionalInterfacesToProxy).ToArray();
		}
예제 #22
0
		public virtual void Generate(ClassEmitter @class, ProxyGenerationOptions options)
		{
			var interceptors = @class.GetField("__interceptors");
#if FEATURE_SERIALIZATION
			ImplementGetObjectData(@class);
#endif
			ImplementProxyTargetAccessor(@class, interceptors);
			foreach (var attribute in targetType.GetTypeInfo().GetNonInheritableAttributes())
			{
				@class.DefineCustomAttribute(attribute.Builder);
			}
		}
		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;
		}
		public virtual void Generate(ClassEmitter @class, ProxyGenerationOptions options)
		{
			var interceptors = @class.GetField("__interceptors");
#if !SILVERLIGHT
			ImplementGetObjectData(@class);
#endif
			ImplementProxyTargetAccessor(@class, interceptors);
			foreach (var attribute in AttributeUtil.GetNonInheritableAttributes(targetType))
			{
				@class.DefineCustomAttribute(attribute);
			}
		}
		protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class,
		                                                      ProxyGenerationOptions options,
		                                                      OverrideMethodDelegate overrideMethod)
		{
			var invocation = GetInvocationType(method, @class, options);
			return new MethodWithInvocationGenerator(method,
			                                         @class.GetField("__interceptors"),
			                                         invocation,
			                                         (c, m) => c.GetField("__target").ToExpression(),
			                                         overrideMethod,
			                                         null);
		}
		protected override ArgumentReference[] GetBaseCtorArguments(Type targetFieldType,
		                                                            ProxyGenerationOptions proxyGenerationOptions,
		                                                            out ConstructorInfo baseConstructor)
		{
			baseConstructor = InvocationMethods.InheritanceInvocationConstructor;
			return new[]
			{
				new ArgumentReference(typeof(Type)),
				new ArgumentReference(typeof(object)),
				new ArgumentReference(typeof(IInterceptor[])),
				new ArgumentReference(typeof(MethodInfo)),
				new ArgumentReference(typeof(object[]))
			};
		}
예제 #27
0
        public override void Generate(ClassEmitter @class, ProxyGenerationOptions options)
        {
            foreach (var @interface in interfaces)
            {
                fields[@interface] = BuildTargetField(@class, @interface);
            }

            foreach (var emptyInterface in empty)
            {
                fields[emptyInterface] = BuildTargetField(@class, emptyInterface);
            }

            base.Generate(@class, options);
        }
		public void Invocation_should_be_IChangeInvocationTarget_for_Mixin_methods()
		{
			var options = new ProxyGenerationOptions();
			options.AddMixinInstance(new Two());
			var interceptor = new ChangeTargetInterceptor(new OneTwo());
			var proxy = generator.CreateInterfaceProxyWithTargetInterface(typeof(IOne),
			                                                              new One(),
			                                                              options,
			                                                              interceptor);

			var result = (proxy as ITwo).TwoMethod();

			Assert.AreEqual(2, result);
		}
		protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class, ProxyGenerationOptions options, CreateMethodDelegate createMethod)
		{
			if (!method.Proxyable)
			{
				return new MinimialisticMethodGenerator(method,
														createMethod);
			}

			var invocation = GetInvocationType(method, @class, options);
			return new MethodWithInvocationGenerator(method,
													 @class.GetField("__interceptors"),
													 invocation,
													 getTargetExpression,
													 createMethod);
		}
		public Type GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options)
		{
			// make sure ProxyGenerationOptions is initialized
			options.Initialize();

			CheckNotGenericTypeDefinition(proxyTargetType, "proxyTargetType");
			CheckNotGenericTypeDefinitions(interfaces, "interfaces");
			EnsureValidBaseType(options.BaseTypeForInterfaceProxy);
			ProxyGenerationOptions = options;

			interfaces = TypeUtil.GetAllInterfaces(interfaces).ToArray();
			var cacheKey = new CacheKey(proxyTargetType, targetType, interfaces, options);

			return ObtainProxyType(cacheKey, (n, s) => GenerateType(n, proxyTargetType, interfaces, s));
		}
예제 #31
0
 protected virtual void CustomizeOptions(ProxyGenerationOptions options, IKernel kernel, ComponentModel model, object[] arguments)
 {
 }
예제 #32
0
 private void ImplementEvent(ClassEmitter emitter, MetaEvent @event, ProxyGenerationOptions options)
 {
     @event.BuildEventEmitter(emitter);
     ImplementMethod(@event.Adder, emitter, options, @event.Emitter.CreateAddMethod);
     ImplementMethod(@event.Remover, emitter, options, @event.Emitter.CreateRemoveMethod);
 }
예제 #33
0
 protected abstract MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class,
                                                         ProxyGenerationOptions options, INamingScope namingScope);
        private T CreateClassProxy <T>()
        {
            var options = new ProxyGenerationOptions(new ProxyNothingHook());

            return((T)generator.CreateClassProxy(typeof(T), Type.EmptyTypes, options));
        }
예제 #35
0
        public object CreateForCollection(object some, IChangeTrackableObject parentObject, PropertyInfo parentObjectProperty)
        {
            if (some.IsTrackable())
            {
                return(some);
            }

            Type collectionType = Configuration.Collections
                                  .GetImplementation(parentObjectProperty.PropertyType).Key;

            Type collectionImplementation;

            if (parentObjectProperty.PropertyType.GetTypeInfo().IsGenericType&& parentObjectProperty.PropertyType == collectionType.MakeGenericType(parentObjectProperty.PropertyType.GenericTypeArguments))
            {
                collectionImplementation = collectionType.MakeGenericType(parentObjectProperty.PropertyType.GenericTypeArguments);
            }
            else
            {
                collectionImplementation = parentObjectProperty.PropertyType.GetInterfaces().SingleOrDefault
                                           (
                    i =>
                {
                    return(i.GetTypeInfo().IsGenericType&& i == collectionType.MakeGenericType(i.GenericTypeArguments[0]));
                }
                                           );
            }

            Contract.Assert(() => collectionImplementation != null);

            if (some == null)
            {
                some = Configuration.Collections
                       .GetImplementation(parentObjectProperty.PropertyType).Value.Type
                       .CreateInstanceWithGenericArgs(null, collectionImplementation.GenericTypeArguments[0]);
            }

            Contract.Assert(() => some != null, "Either if a collection object is provided or not, a proxied instance of the whole collection type must be created");

            Type genericCollectionType  = some.GetType().GetGenericArguments().Last();
            bool canTrackCollectionType = Configuration.CanTrackType(genericCollectionType);

            ProxyGenerationOptions         options             = new ProxyGenerationOptions(new CollectionterceptionHook());
            ChangeTrackableCollectionMixin changeTrackingMixin = new ChangeTrackableCollectionMixin();

            changeTrackingMixin.GetChangeTrackingContext().Configuration = Configuration;
            options.AddMixinInstance(changeTrackingMixin);

            KeyValuePair <Type, CollectionImplementation> collectionImplementationDetail
                = Configuration.Collections.GetImplementation(parentObjectProperty.PropertyType);

            Contract.Assert(() => collectionImplementationDetail.Key.MakeGenericType(collectionImplementation.GenericTypeArguments).IsAssignableFrom(parentObjectProperty.PropertyType), $"Trackable collection implementation of type '{collectionImplementationDetail.Key.AssemblyQualifiedName}' cannot be set to the target property '{parentObjectProperty.DeclaringType.FullName}.{parentObjectProperty.Name}' with type '{parentObjectProperty.PropertyType.AssemblyQualifiedName}'. This isn't supported because it might require a downcast. Please provide a collection change tracking configuration to work with the more concrete interface.");

            object targetList;

            if (!canTrackCollectionType)
            {
                targetList = some;
            }
            else
            {
                targetList = collectionImplementationDetail.Value.Type.CreateInstanceWithGenericArgs
                             (
                    new[]
                {
                    typeof(EnumerableExtensions).GetMethod("MakeAllTrackable")
                    .MakeGenericMethod(genericCollectionType)
                    .Invoke(null, new[] { some, Configuration, this, parentObjectProperty, parentObject })
                },
                    genericCollectionType
                             );
            }

            Contract.Assert(() => targetList != null, "List to proxy is mandatory");

            IChangeTrackableCollection proxy = (IChangeTrackableCollection)ProxyGenerator.CreateInterfaceProxyWithTarget
                                               (
                collectionImplementationDetail.Key.MakeGenericType(some.GetType().GetGenericArguments()),
                new[] { typeof(IChangeTrackableCollection), typeof(IReadOnlyChangeTrackableCollection) },
                targetList,
                options,
                new CollectionPropertyInterceptor(Configuration, this)
                                               );

            proxy.ParentObject         = parentObject;
            proxy.ParentObjectProperty = parentObjectProperty;

            proxy.CollectionChanged += (sender, e) =>
                                       parentObject.RaisePropertyChanged(parentObject, parentObjectProperty.Name);

            return(proxy);
        }
        protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, 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 dereferencedArguments = IndirectReference.WrapIfByRef(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);
            }

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

            emitter.CodeBuilder.AddStatement(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);
        }
예제 #37
0
 private Type GetInvocationType(MetaMethod method, ClassEmitter @class, ProxyGenerationOptions options)
 {
     // NOTE: No caching since invocation is tied to this specific proxy type via its invocation method
     return(BuildInvocationType(method, @class, options));
 }
예제 #38
0
 public CastleProxyFactory()
 {
     this.generationOptions = new ProxyGenerationOptions {
         Hook = new IncludeObjectMethodsHook(), BaseTypeForInterfaceProxy = typeof(InterfaceProxy)
     };
 }
        public void Init()
#endif
        {
            _options1 = new ProxyGenerationOptions();
            _options2 = new ProxyGenerationOptions();
        }
예제 #40
0
        /// <summary>
        /// Enable interface interception on the target type. Interceptors will be determined
        /// via Intercept attributes on the class or interface, or added with InterceptedBy() calls.
        /// </summary>
        /// <typeparam name="TLimit">Registration limit type.</typeparam>
        /// <typeparam name="TActivatorData">Activator data type.</typeparam>
        /// <typeparam name="TSingleRegistrationStyle">Registration style.</typeparam>
        /// <param name="registration">Registration to apply interception to.</param>
        /// <param name="options">Proxy generation options to apply.</param>
        /// <returns>Registration builder allowing the registration to be configured.</returns>
        public static IRegistrationBuilder <TLimit, TActivatorData, TSingleRegistrationStyle> EnableInterfaceInterceptors <TLimit, TActivatorData, TSingleRegistrationStyle>(
            this IRegistrationBuilder <TLimit, TActivatorData, TSingleRegistrationStyle> registration, ProxyGenerationOptions options = null)
        {
            if (registration == null)
            {
                throw new ArgumentNullException(nameof(registration));
            }

            registration.RegistrationData.ActivatingHandlers.Add((_, e) =>
            {
                EnsureInterfaceInterceptionApplies(e.Component);

                var proxiedInterfaces = e.Instance
                                        .GetType()
                                        .GetInterfaces()
                                        .Where(ProxyUtil.IsAccessible)
                                        .ToArray();

                if (!proxiedInterfaces.Any())
                {
                    return;
                }

                var theInterface = proxiedInterfaces.First();
                var interfaces   = proxiedInterfaces.Skip(1).ToArray();

                var interceptors = GetInterceptorServices(e.Component, e.Instance.GetType())
                                   .Select(s => e.Context.ResolveService(s))
                                   .Cast <IInterceptor>()
                                   .ToArray();

                e.Instance = options == null
                    ? ProxyGenerator.CreateInterfaceProxyWithTarget(theInterface, interfaces, e.Instance, interceptors)
                    : ProxyGenerator.CreateInterfaceProxyWithTarget(theInterface, interfaces, e.Instance, options, interceptors);
            });

            return(registration);
        }
예제 #41
0
        /// <summary>
        /// Intercepts the interface of a transparent proxy (such as WCF channel factory based clients).
        /// </summary>
        /// <typeparam name="TLimit">Registration limit type.</typeparam>
        /// <typeparam name="TActivatorData">Activator data type.</typeparam>
        /// <typeparam name="TSingleRegistrationStyle">Registration style.</typeparam>
        /// <param name="registration">Registration to apply interception to.</param>
        /// <param name="options">Proxy generation options to apply.</param>
        /// <param name="additionalInterfacesToProxy">Additional interface types. Calls to their members will be proxied as well.</param>
        /// <returns>Registration builder allowing the registration to be configured.</returns>
        public static IRegistrationBuilder <TLimit, TActivatorData, TSingleRegistrationStyle> InterceptTransparentProxy <TLimit, TActivatorData, TSingleRegistrationStyle>(
            this IRegistrationBuilder <TLimit, TActivatorData, TSingleRegistrationStyle> registration, ProxyGenerationOptions options, params Type[] additionalInterfacesToProxy)
        {
            if (registration == null)
            {
                throw new ArgumentNullException(nameof(registration));
            }

            registration.RegistrationData.ActivatingHandlers.Add((sender, e) =>
            {
                EnsureInterfaceInterceptionApplies(e.Component);

                if (!RemotingServices.IsTransparentProxy(e.Instance))
                {
                    throw new DependencyResolutionException(string.Format(
                                                                CultureInfo.CurrentCulture, RegistrationExtensionsResources.TypeIsNotTransparentProxy, e.Instance.GetType().FullName));
                }

                var instanceType     = e.Instance.GetType();
                var instanceTypeInfo = instanceType.GetTypeInfo();
                if (!instanceTypeInfo.IsInterface)
                {
                    throw new DependencyResolutionException(string.Format(
                                                                CultureInfo.CurrentCulture, RegistrationExtensionsResources.TransparentProxyIsNotInterface, e.Instance.GetType().FullName));
                }

                if (additionalInterfacesToProxy.Any())
                {
                    var remotingTypeInfo = (IRemotingTypeInfo)RemotingServices.GetRealProxy(e.Instance);

                    var invalidInterfaces = additionalInterfacesToProxy
                                            .Where(i => !remotingTypeInfo.CanCastTo(i, e.Instance))
                                            .ToArray();

                    if (invalidInterfaces.Any())
                    {
                        string message = string.Format(
                            CultureInfo.CurrentCulture,
                            RegistrationExtensionsResources.InterfaceNotSupportedByTransparentProxy,
                            string.Join(", ", invalidInterfaces.Select(i => i.FullName)));
                        throw new DependencyResolutionException(message);
                    }
                }

                var interceptors = GetInterceptorServices(e.Component, instanceType)
                                   .Select(s => e.Context.ResolveService(s))
                                   .Cast <IInterceptor>()
                                   .ToArray();

                e.Instance = options == null
                ? ProxyGenerator.CreateInterfaceProxyWithTargetInterface(instanceType, additionalInterfacesToProxy, e.Instance, interceptors)
                : ProxyGenerator.CreateInterfaceProxyWithTargetInterface(instanceType, additionalInterfacesToProxy, e.Instance, options, interceptors);
            });

            return(registration);
        }
        protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class, ProxyGenerationOptions options, CreateMethodDelegate createMethod)
        {
            if (!method.Proxyable)
            {
                return(new MinimialisticMethodGenerator(method,
                                                        createMethod));
            }

            var invocation = GetInvocationType(method, @class, options);

            return(new MethodWithInvocationGenerator(method,
                                                     @class.GetField("__interceptors"),
                                                     invocation,
                                                     getTargetExpression,
                                                     createMethod));
        }
예제 #43
0
 public ClassProxyGenerator(ModuleScope scope, Type targetType, Type[] interfaces, ProxyGenerationOptions options)
     : base(scope, targetType, interfaces, options)
 {
 }
예제 #44
0
 protected virtual void CustomizeProxy(object proxy, ProxyGenerationOptions options, IKernel kernel, ComponentModel model)
 {
 }
예제 #45
0
파일: CacheKey.cs 프로젝트: fniwes/n2cms
 /// <summary>
 ///   Initializes a new instance of the <see cref = "CacheKey" /> class.
 /// </summary>
 /// <param name = "target">Type of the target.</param>
 /// <param name = "interfaces">The interfaces.</param>
 /// <param name = "options">The options.</param>
 public CacheKey(Type target, Type[] interfaces, ProxyGenerationOptions options)
     : this(target, null, interfaces, options)
 {
 }
예제 #46
0
 public Type CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
 {
     throw new NotImplementedException();
 }
예제 #47
0
        protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class, ProxyGenerationOptions options, CreateMethodDelegate createMethod)
        {
            if (methodsToSkip.Contains(method.Method))
            {
                return(null);
            }

            if (!method.Proxyable)
            {
                return(new MinimialisticMethodGenerator(method,
                                                        createMethod));
            }

            var invocation = GetInvocationType(method, @class, options);

            return(new MethodWithInvocationGenerator(method,
                                                     @class.GetField("__interceptors"),
                                                     invocation,
                                                     (c, m) => new TypeTokenExpression(targetType),
                                                     createMethod));
        }
예제 #48
0
 public Type CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
 {
     throw new NotImplementedException();
 }
예제 #49
0
        public object Create(object some = null, Type typeToTrack = null, ObjectChangeTracker reusedTracker = null, object parentObject = null, PropertyInfo propertyToSet = null, object[] constructorArguments = null)
        {
            typeToTrack = typeToTrack ?? some.GetType();

            ITrackableType interfaceTrackableType = null;

            if ((Configuration.CanTrackType(typeToTrack) || Configuration.ImplementsBaseType(typeToTrack, out interfaceTrackableType)) && !typeToTrack.IsTrackable())
            {
                if (interfaceTrackableType != null)
                {
                    Configuration.TrackThisTypeRecursive
                    (
                        typeToTrack,
                        trackableType =>
                    {
                        if (trackableType.Type == typeToTrack)
                        {
                            trackableType.IncludeProperties(interfaceTrackableType.IncludedProperties.ToArray());
                        }
                    }
                    );
                }

                TypeInfo typeToTrackInfo = typeToTrack.GetTypeInfo();

                Contract.Assert(() => typeToTrackInfo.IsClass && !typeToTrackInfo.IsAbstract && !typeToTrackInfo.IsSealed, $"The object type to track '{typeToTrack.AssemblyQualifiedName}' must be a non-abstract, non-sealed class");

                ProxyGenerationOptions options = new ProxyGenerationOptions(new SimplePropertyInterceptionHook(Configuration));
                options.AddMixinInstance(new ChangeTrackableObjectMixin(Configuration, this));
                options.AdditionalAttributes.Add(AttributeUtil.CreateInfo(typeof(DebuggerDisplayAttribute), new[] { $"{typeToTrack.FullName}Proxy" }));

                List <IInterceptor> interceptors = new List <IInterceptor>
                {
                    new SimplePropertyInterceptor()
                };

                if (typeToTrack.IsDynamicObject())
                {
                    interceptors.Add(new DynamicObjectInterceptor(Configuration, this));
                }

                object proxy;

                if (some != null)
                {
                    proxy = ProxyGenerator.CreateClassProxyWithTarget
                            (
                        classToProxy: typeToTrack,
                        additionalInterfacesToProxy: new[] { typeof(IChangeTrackableObject) },
                        target: some,
                        options: options,
                        interceptors: interceptors.ToArray()
                            );
                }
                else
                {
                    proxy = ProxyGenerator.CreateClassProxy
                            (
                        classToProxy: typeToTrack,
                        additionalInterfacesToProxy: new[] { typeof(IChangeTrackableObject) },
                        options: options,
                        constructorArguments: constructorArguments,
                        interceptors: interceptors.ToArray()
                            );
                }


                IChangeTrackableObject      trackableObject = (IChangeTrackableObject)proxy;
                ObjectChangeTrackingContext trackingContext = trackableObject.GetChangeTrackingContext();

                trackingContext.State = ChangeTrackableObjectState.Constructing;
                trackableObject.StartTracking(trackableObject, reusedTracker);
                trackingContext.State = ChangeTrackableObjectState.Ready;

                HashSet <PropertyInfo> propertiesToTrack =
                    new HashSet <PropertyInfo>(Configuration.GetTrackableType(typeToTrack).IncludedProperties);

                if (propertiesToTrack.Count() == 0)
                {
                    foreach (PropertyInfo property in typeToTrack.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                    {
                        propertiesToTrack.Add(property);
                    }
                }

                foreach (PropertyInfo property in propertiesToTrack)
                {
                    if (!property.IsIndexer() && property.CanReadAndWrite())
                    {
                        object propertyValue = property.GetValue(trackableObject);

                        if (propertyValue != null)
                        {
                            Create(propertyValue, trackableObject.GetChangeTrackingContext().ChangeTracker, proxy, property);
                        }
                        else
                        {
                            Create(property.PropertyType, trackableObject.GetChangeTrackingContext().ChangeTracker, proxy, property);
                        }
                    }
                }

                if (propertyToSet != null)
                {
                    propertyToSet.SetValue(parentObject ?? proxy, proxy);
                }

                trackableObject.AcceptChanges();

                return(proxy);
            }
            else
            {
                return(some);
            }
        }
예제 #50
0
        protected BaseProxyGenerator(ModuleScope scope, Type targetType, Type[] interfaces, ProxyGenerationOptions proxyGenerationOptions)
        {
            CheckNotGenericTypeDefinition(targetType, nameof(targetType));
            CheckNotGenericTypeDefinitions(interfaces, nameof(interfaces));

            this.scope                  = scope;
            this.targetType             = targetType;
            this.interfaces             = TypeUtil.GetAllInterfaces(interfaces);
            this.proxyGenerationOptions = proxyGenerationOptions;
            this.proxyGenerationOptions.Initialize();
        }
예제 #51
0
        protected override ArgumentReference[] GetCtorArgumentsAndBaseCtorToCall(Type targetFieldType, ProxyGenerationOptions proxyGenerationOptions, out ConstructorInfo baseConstructor)
        {
            if (proxyGenerationOptions.Selector == null)
            {
                baseConstructor = InvocationMethods.InheritanceInvocationConstructorNoSelector;
                return(new[]
                {
                    new ArgumentReference(typeof(Type)),
                    new ArgumentReference(typeof(object)),
                    new ArgumentReference(typeof(IInterceptor[])),
                    new ArgumentReference(typeof(MethodInfo)),
                    new ArgumentReference(typeof(object[]))
                });
            }

            baseConstructor = InvocationMethods.InheritanceInvocationConstructorWithSelector;
            return(new[]
            {
                new ArgumentReference(typeof(Type)),
                new ArgumentReference(typeof(object)),
                new ArgumentReference(typeof(IInterceptor[])),
                new ArgumentReference(typeof(MethodInfo)),
                new ArgumentReference(typeof(object[])),
                new ArgumentReference(typeof(IInterceptorSelector)),
                new ArgumentReference(typeof(IInterceptor[]).MakeByRefType())
            });
        }
예제 #52
0
 public InterfaceProxyWithTargetInterfaceGenerator(ModuleScope scope, Type @interface, ProxyGenerationOptions options)
     : base(scope, @interface, options)
 {
 }
예제 #53
0
        public IWampClientProxy <TMessage> Create(IWampConnection <TMessage> connection)
        {
            IWampOutgoingMessageHandler outgoingHandler =
                mOutgoingHandlerBuilder.Build(connection);

            WampOutgoingInterceptor <TMessage> wampOutgoingInterceptor =
                new WampOutgoingInterceptor <TMessage>
                    (mOutgoingSerializer,
                    outgoingHandler);

            WampRawOutgoingInterceptor <TMessage> wampRawOutgoingInterceptor =
                new WampRawOutgoingInterceptor <TMessage>(outgoingHandler);

            ProxyGenerationOptions proxyGenerationOptions =
                new ProxyGenerationOptions()
            {
                Selector =
                    new WampInterceptorSelector <TMessage>()
            };

            WampConnectionMonitor <TMessage> monitor =
                new WampConnectionMonitor <TMessage>(connection);

            proxyGenerationOptions.AddMixinInstance(monitor);

            proxyGenerationOptions.AddMixinInstance
                (new WampClientContainerDisposable <TMessage, IWampClientProxy <TMessage> >
                    (mContainer, connection));

            WampTransportDetails transportDetails = null;

            IDetailedWampConnection <TMessage> detailedConnection =
                connection as IDetailedWampConnection <TMessage>;

            if (detailedConnection != null)
            {
                transportDetails = detailedConnection.TransportDetails;
            }

            WampClientPropertyBag <TMessage> propertyBag =
                new WampClientPropertyBag <TMessage>(mBinding, transportDetails);

            proxyGenerationOptions.AddMixinInstance(propertyBag);

            IWampAuthenticatedConnection <TMessage> authenticatedConnection =
                connection as IWampAuthenticatedConnection <TMessage>;

            if (authenticatedConnection != null)
            {
                propertyBag.Authenticator = authenticatedConnection.Authenticator;
            }

            IWampClientProxy <TMessage> result =
                mGenerator.CreateInterfaceProxyWithoutTarget
                    (typeof(IWampProxy), new[] { typeof(IWampClientProxy <TMessage>) },
                    proxyGenerationOptions,
                    wampRawOutgoingInterceptor,
                    wampOutgoingInterceptor)
                as IWampClientProxy <TMessage>;

            monitor.Client = result;

            long session = (long)mContainer.GenerateClientId(result);

            propertyBag.Session = session;

            return(result);
        }
 /// <summary>
 ///   Generates the constructor for the class that extends
 ///   <see cref = "AbstractInvocation" />
 /// </summary>
 /// <param name = "targetFieldType"></param>
 /// <param name = "proxyGenerationOptions"></param>
 /// <param name = "baseConstructor"></param>
 protected abstract ArgumentReference[] GetBaseCtorArguments(Type targetFieldType,
                                                             ProxyGenerationOptions proxyGenerationOptions,
                                                             out ConstructorInfo baseConstructor);
예제 #55
0
 protected abstract MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class,
                                                       ProxyGenerationOptions options,
                                                       OverrideMethodDelegate overrideMethod);
        protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope)
        {
            var invocationType = invocation;

            Trace.Assert(MethodToOverride.IsGenericMethod == invocationType.GetTypeInfo().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.GetTypeInfo().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);
        }
예제 #57
0
 public DelegateProxyGenerator(ModuleScope scope, Type delegateType) : base(scope, delegateType)
 {
     ProxyGenerationOptions = new ProxyGenerationOptions(new DelegateProxyGenerationHook());
     ProxyGenerationOptions.Initialize();
 }
예제 #58
0
 public InterfaceProxyWithTargetInterfaceGenerator(ModuleScope scope, Type targetType, Type[] interfaces,
                                                   Type proxyTargetType, ProxyGenerationOptions options)
     : base(scope, targetType, interfaces, proxyTargetType, options)
 {
 }
        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);
        }
예제 #60
0
        public Type CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
        {
            AssertValidType(interfaceToProxy);
            AssertValidTypes(additionalInterfacesToProxy);

            var generator = new InterfaceProxyWithoutTargetGenerator(ModuleScope, interfaceToProxy)
            {
                Logger = Logger
            };

            return(generator.GenerateCode(typeof(object), additionalInterfacesToProxy, options));
        }