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()) }; }
/// <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); } }
/// <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; }
/// <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); }
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)); }
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); }
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(); }
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[])) }; }
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)); }
protected virtual void CustomizeOptions(ProxyGenerationOptions options, IKernel kernel, ComponentModel model, object[] arguments) { }
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); }
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)); }
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); }
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)); }
public CastleProxyFactory() { this.generationOptions = new ProxyGenerationOptions { Hook = new IncludeObjectMethodsHook(), BaseTypeForInterfaceProxy = typeof(InterfaceProxy) }; }
public void Init() #endif { _options1 = new ProxyGenerationOptions(); _options2 = new ProxyGenerationOptions(); }
/// <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); }
/// <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)); }
public ClassProxyGenerator(ModuleScope scope, Type targetType, Type[] interfaces, ProxyGenerationOptions options) : base(scope, targetType, interfaces, options) { }
protected virtual void CustomizeProxy(object proxy, ProxyGenerationOptions options, IKernel kernel, ComponentModel model) { }
/// <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) { }
public Type CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options) { throw new NotImplementedException(); }
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)); }
public Type CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options) { throw new NotImplementedException(); }
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); } }
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(); }
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()) }); }
public InterfaceProxyWithTargetInterfaceGenerator(ModuleScope scope, Type @interface, ProxyGenerationOptions options) : base(scope, @interface, options) { }
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);
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); }
public DelegateProxyGenerator(ModuleScope scope, Type delegateType) : base(scope, delegateType) { ProxyGenerationOptions = new ProxyGenerationOptions(new DelegateProxyGenerationHook()); ProxyGenerationOptions.Initialize(); }
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); }
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)); }