protected virtual ITypeContributor AddMappingForTargetType(IDictionary<Type, ITypeContributor> typeImplementerMapping, Type proxyTargetType, ICollection<Type> targetInterfaces, ICollection<Type> additionalInterfaces, INamingScope namingScope) { var contributor = new InterfaceProxyTargetContributor(proxyTargetType, AllowChangeTarget, namingScope) { Logger = Logger }; var proxiedInterfaces = targetType.GetAllInterfaces(); foreach (var @interface in proxiedInterfaces) { contributor.AddInterfaceToProxy(@interface); AddMappingNoCheck(@interface, contributor, typeImplementerMapping); } foreach (var @interface in additionalInterfaces) { if (!ImplementedByTarget(targetInterfaces, @interface) || proxiedInterfaces.Contains(@interface)) { continue; } contributor.AddInterfaceToProxy(@interface); AddMappingNoCheck(@interface, contributor, typeImplementerMapping); } return contributor; }
public ClassProxyWithTargetTargetContributor(Type targetType, IList<MethodInfo> methodsToSkip, INamingScope namingScope) : base(namingScope) { this.targetType = targetType; this.methodsToSkip = methodsToSkip; }
protected virtual IEnumerable<Type> GetTypeImplementerMapping(out IEnumerable<ITypeContributor> contributors, INamingScope namingScope) { var methodsToSkip = new List<MethodInfo>(); var proxyInstance = new ClassProxyInstanceContributor(targetType, methodsToSkip, Type.EmptyTypes, ProxyTypeConstants.ClassWithTarget); var proxyTarget = new DelegateProxyTargetContributor(targetType, namingScope) { Logger = Logger }; IDictionary<Type, ITypeContributor> typeImplementerMapping = new Dictionary<Type, ITypeContributor>(); // Order of interface precedence: // 1. first target, target is not an interface so we do nothing // 2. then mixins - we support none so we do nothing // 3. then additional interfaces - we support none so we do nothing #if !SILVERLIGHT // 4. plus special interfaces if (targetType.IsSerializable) { AddMappingForISerializable(typeImplementerMapping, proxyInstance); } #endif AddMappingNoCheck(typeof(IProxyTargetAccessor), proxyInstance, typeImplementerMapping); contributors = new List<ITypeContributor> { proxyTarget, proxyInstance }; return typeImplementerMapping.Keys; }
public InterfaceProxyWithOptionalTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget, GetTargetReferenceDelegate getTargetReference) : base(namingScope, getTarget) { this.getTargetReference = getTargetReference; canChangeTarget = true; }
public InvocationWithDelegateContributor(Type delegateType, Type targetType,MetaMethod method, INamingScope namingScope) { Debug.Assert(delegateType.IsGenericType == false, "delegateType.IsGenericType == false"); this.delegateType = delegateType; this.targetType = targetType; this.method = method; this.namingScope = namingScope; }
private Type GenerateType(string name, INamingScope namingScope) { IEnumerable<ITypeContributor> contributors; var implementedInterfaces = GetTypeImplementerMapping(out contributors, namingScope); var model = new MetaType(); // Collect methods foreach (var contributor in contributors) { contributor.CollectElementsToProxy(ProxyGenerationOptions.Hook, model); } ProxyGenerationOptions.Hook.MethodsInspected(); var emitter = BuildClassEmitter(name, targetType, implementedInterfaces); CreateFields(emitter); CreateTypeAttributes(emitter); // Constructor var cctor = GenerateStaticConstructor(emitter); var targetField = CreateTargetField(emitter); var constructorArguments = new List<FieldReference> { targetField }; foreach (var contributor in contributors) { contributor.Generate(emitter, ProxyGenerationOptions); // TODO: redo it if (contributor is MixinContributor) { constructorArguments.AddRange((contributor as MixinContributor).Fields); } } // constructor arguments var interceptorsField = emitter.GetField("__interceptors"); constructorArguments.Add(interceptorsField); var selector = emitter.GetField("__selector"); if (selector != null) { constructorArguments.Add(selector); } GenerateConstructors(emitter, targetType, constructorArguments.ToArray()); GenerateParameterlessConstructor(emitter, targetType, interceptorsField); // Complete type initializer code body CompleteInitCacheMethod(cctor.CodeBuilder); // Crosses fingers and build type Type proxyType = emitter.BuildType(); InitializeStaticFields(proxyType); return proxyType; }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { var targetReference = getTargetReference(@class, MethodToOverride); emitter.CodeBuilder.AddStatement( new ExpressionStatement( new IfNullExpression(targetReference, IfNull(emitter.ReturnType), IfNotNull(targetReference)))); return emitter; }
protected override ITypeContributor AddMappingForTargetType(IDictionary<Type, ITypeContributor> interfaceTypeImplementerMapping, Type proxyTargetType, ICollection<Type> targetInterfaces, ICollection<Type> additionalInterfaces, INamingScope namingScope) { var contributor = new InterfaceProxyWithoutTargetContributor(namingScope, (c, m) => NullExpression.Instance) { Logger = Logger }; foreach (var @interface in TypeUtil.GetAllInterfaces(targetType)) { contributor.AddInterfaceToProxy(@interface); AddMappingNoCheck(@interface, contributor, interfaceTypeImplementerMapping); } return contributor; }
protected FieldReference BuildMethodInterceptorsField(ClassEmitter @class, MethodInfo method, INamingScope namingScope) { var methodInterceptors = @class.CreateField( namingScope.GetUniqueName(string.Format("interceptors_{0}", method.Name)), typeof(IInterceptor[]), false); #if !SILVERLIGHT @class.DefineCustomAttributeFor<XmlIgnoreAttribute>(methodInterceptors); #endif return methodInterceptors; }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { var targetReference = getTargetReference(@class, MethodToOverride); var arguments = ArgumentsUtil.ConvertToArgumentReferenceExpression(MethodToOverride.GetParameters()); emitter.CodeBuilder.AddStatement(new ReturnStatement( new MethodInvocationExpression( targetReference, MethodToOverride, arguments) { VirtualCall = true })); return emitter; }
protected override Type GenerateType(string typeName, Type proxyTargetType, Type[] interfaces, INamingScope namingScope) { IEnumerable<ITypeContributor> contributors; var allInterfaces = GetTypeImplementerMapping(interfaces, targetType, out contributors, namingScope); var model = new MetaType(); // collect elements foreach (var contributor in contributors) { contributor.CollectElementsToProxy(ProxyGenerationOptions.Hook, model); } ProxyGenerationOptions.Hook.MethodsInspected(); ClassEmitter emitter; FieldReference interceptorsField; var baseType = Init(typeName, out emitter, proxyTargetType, out interceptorsField, allInterfaces); // Constructor var cctor = GenerateStaticConstructor(emitter); var mixinFieldsList = new List<FieldReference>(); foreach (var contributor in contributors) { contributor.Generate(emitter, ProxyGenerationOptions); // TODO: redo it if (contributor is MixinContributor) { mixinFieldsList.AddRange((contributor as MixinContributor).Fields); } } var ctorArguments = new List<FieldReference>(mixinFieldsList) { interceptorsField, targetField }; var selector = emitter.GetField("__selector"); if (selector != null) { ctorArguments.Add(selector); } GenerateConstructors(emitter, baseType, ctorArguments.ToArray()); // Complete type initializer code body CompleteInitCacheMethod(cctor.CodeBuilder); // Crosses fingers and build type var generatedType = emitter.BuildType(); InitializeStaticFields(generatedType); return generatedType; }
protected override ITypeContributor AddMappingForTargetType(IDictionary<Type, ITypeContributor> typeImplementerMapping, Type proxyTargetType, ICollection<Type> targetInterfaces, ICollection<Type> additionalInterfaces, INamingScope namingScope) { WCFInterfaceProxyWithTargetInterfaceTargetContributor contributor = new WCFInterfaceProxyWithTargetInterfaceTargetContributor(proxyTargetType, this.AllowChangeTarget, namingScope) { Logger = base.Logger }; foreach (Type @interface in base.targetType.GetAllInterfaces()) { contributor.AddInterfaceToProxy(@interface); base.AddMappingNoCheck(@interface, contributor, typeImplementerMapping); } return contributor; }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { InitOutParameters(emitter, MethodToOverride.GetParameters()); if (emitter.ReturnType == typeof(void)) { emitter.CodeBuilder.AddStatement(new ReturnStatement()); } else { emitter.CodeBuilder.AddStatement(new ReturnStatement(new DefaultValueExpression(emitter.ReturnType))); } return emitter; }
protected override Type GenerateType(string typeName, Type proxyTargetType, Type[] interfaces, INamingScope namingScope) { IEnumerable<ITypeContributor> contributors; ClassEmitter emitter; FieldReference interceptorsField; IEnumerable<Type> allInterfaces = this.GetTypeImplementerMapping(interfaces, base.targetType, out contributors, namingScope); MetaType model = new MetaType(); foreach (ITypeContributor contributor in contributors) { contributor.CollectElementsToProxy(base.ProxyGenerationOptions.Hook, model); } base.ProxyGenerationOptions.Hook.MethodsInspected(); Type baseType = this.Init(typeName, out emitter, proxyTargetType, out interceptorsField, allInterfaces); ConstructorEmitter cctor = base.GenerateStaticConstructor(emitter); List<FieldReference> mixinFieldsList = new List<FieldReference>(); foreach (ITypeContributor contributor in contributors) { contributor.Generate(emitter, base.ProxyGenerationOptions); if (contributor is MixinContributor) { mixinFieldsList.AddRange((contributor as MixinContributor).Fields); } } List<FieldReference> g__initLocalc = new List<FieldReference>(mixinFieldsList) { interceptorsField, base.targetField }; List<FieldReference> ctorArguments = g__initLocalc; FieldReference selector = emitter.GetField("__selector"); if (selector != null) { ctorArguments.Add(selector); } base.GenerateConstructors(emitter, baseType, ctorArguments.ToArray()); base.CompleteInitCacheMethod(cctor.CodeBuilder); Type generatedType = emitter.BuildType(); base.InitializeStaticFields(generatedType); return generatedType; }
public MixinContributor(INamingScope namingScope, bool canChangeTarget) : base(namingScope) { this.canChangeTarget = canChangeTarget; getTargetExpression = BuildGetTargetExpression(); }
private EntityProxyNameScope(INamingScope parent) { this.parentScope = parent; }
public DelegateProxyTargetContributor(Type targetType, INamingScope namingScope) : base(namingScope) { this.targetType = targetType; }
protected override InterfaceProxyWithoutTargetContributor GetContributorForAdditionalInterfaces( INamingScope namingScope) { return new InterfaceProxyWithOptionalTargetContributor(namingScope, GetTargetExpression, GetTarget) { Logger = Logger }; }
/// <summary> /// Initializes a new instance of the <see cref = "ModuleScope" /> class, allowing to specify whether the assemblies generated by this instance /// should be saved and what simple names are to be assigned to them. /// </summary> /// <param name = "savePhysicalAssembly">If set to <c>true</c> saves the generated module.</param> /// <param name = "disableSignedModule">If set to <c>true</c> disables ability to generate signed module. This should be used in cases where ran under constrained permissions.</param> /// <param name = "namingScope">Naming scope used to provide unique names to generated types and their members (usually via sub-scopes).</param> /// <param name = "strongAssemblyName">The simple name of the strong-named assembly generated by this <see /// cref = "ModuleScope" />.</param> /// <param name = "strongModulePath">The path and file name of the manifest module of the strong-named assembly generated by this <see /// cref = "ModuleScope" />.</param> /// <param name = "weakAssemblyName">The simple name of the weak-named assembly generated by this <see cref = "ModuleScope" />.</param> /// <param name = "weakModulePath">The path and file name of the manifest module of the weak-named assembly generated by this <see /// cref = "ModuleScope" />.</param> public ModuleScope(bool savePhysicalAssembly, bool disableSignedModule, INamingScope namingScope, string strongAssemblyName, string strongModulePath, string weakAssemblyName, string weakModulePath) { this.savePhysicalAssembly = savePhysicalAssembly; this.disableSignedModule = disableSignedModule; this.namingScope = namingScope; this.strongAssemblyName = strongAssemblyName; this.strongModulePath = strongModulePath; this.weakAssemblyName = weakAssemblyName; this.weakModulePath = weakModulePath; this.internalsUtil = new InternalsUtil(this); }
private EntityProxyNameScope( INamingScope parent ) { this.parentScope = parent; }
public ClassProxyTargetContributor(Type targetType, IList <MethodInfo> methodsToSkip, INamingScope namingScope) : base(namingScope) { this.targetType = targetType; this.methodsToSkip = methodsToSkip; }
protected override ITypeContributor AddMappingForTargetType( IDictionary <Type, ITypeContributor> interfaceTypeImplementerMapping, Type proxyTargetType, ICollection <Type> targetInterfaces, ICollection <Type> additionalInterfaces, INamingScope namingScope) { var contributor = new InterfaceProxyWithoutTargetContributor(namingScope, Scope, (c, m) => NullExpression.Instance) { Logger = Logger }; foreach (var @interface in targetType.GetAllInterfaces()) { contributor.AddInterfaceToProxy(@interface); AddMappingNoCheck(@interface, contributor, interfaceTypeImplementerMapping); } return(contributor); }
public InterfaceProxyTargetContributor(Type proxyTargetType, bool canChangeTarget, INamingScope namingScope) : base(namingScope) { this.proxyTargetType = proxyTargetType; this.canChangeTarget = canChangeTarget; }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { var invocationType = invocation; Trace.Assert(MethodToOverride.IsGenericMethod == invocationType.IsGenericTypeDefinition()); var genericArguments = TypeExtender.EmptyTypes; var constructor = invocation.GetConstructors()[0]; Expression proxiedMethodTokenExpression; if (MethodToOverride.IsGenericMethod) { // bind generic method arguments to invocation's type arguments genericArguments = emitter.MethodBuilder.GetGenericArguments(); invocationType = invocationType.MakeGenericType(genericArguments); constructor = TypeBuilder.GetConstructor(invocationType, constructor); // Not in the cache: generic method proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericArguments)); } else { var proxiedMethodToken = @class.CreateStaticField(namingScope.GetUniqueName("token_" + MethodToOverride.Name), typeof(MethodInfo)); @class.ClassConstructor.CodeBuilder.AddStatement(new AssignStatement(proxiedMethodToken, new MethodTokenExpression(MethodToOverride))); proxiedMethodTokenExpression = proxiedMethodToken.ToExpression(); } var dereferencedArguments = IndirectReference.WrapIfByRef(emitter.Arguments); var hasByRefArguments = HasByRefArguments(emitter.Arguments); var arguments = GetCtorArguments(@class, namingScope, proxiedMethodTokenExpression, dereferencedArguments); var ctorArguments = ModifyArguments(@class, arguments); var invocationLocal = emitter.CodeBuilder.DeclareLocal(invocationType); emitter.CodeBuilder.AddStatement(new AssignStatement(invocationLocal, new NewInstanceExpression(constructor, ctorArguments))); if (MethodToOverride.ContainsGenericParameters) { EmitLoadGenricMethodArguments(emitter, MethodToOverride.MakeGenericMethod(genericArguments), invocationLocal); } if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new TryStatement()); } var proceed = new ExpressionStatement(new MethodInvocationExpression(invocationLocal, InvocationMethods.Proceed)); emitter.CodeBuilder.AddStatement(proceed); if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new FinallyStatement()); } GeneratorUtil.CopyOutAndRefParameters(dereferencedArguments, invocationLocal, MethodToOverride, emitter); if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new EndExceptionBlockStatement()); } if (MethodToOverride.ReturnType != typeof(void)) { // Emit code to return with cast from ReturnValue // @mbrit - 2012-05-31 - see the note associated with the GetReturnValueForWinRt declaration // for more information on this... var useWinRtGenericHandler = false; #if NETFX_CORE if (emitter.ReturnType == typeof(int) || emitter.ReturnType == typeof(bool)) { useWinRtGenericHandler = true; } #endif if (!(useWinRtGenericHandler)) { var getRetVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue); emitter.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(emitter.ReturnType, getRetVal))); } else { #if NETFX_CORE var grvArgs = new Type[] { emitter.ReturnType }; var grvCall = InvocationMethods.GetReturnValueForWinRt.MakeGenericMethod(grvArgs); var getRetVal = new MethodInvocationExpression(invocationLocal, grvCall); emitter.CodeBuilder.AddStatement(new ReturnStatement(getRetVal)); #endif } } else { emitter.CodeBuilder.AddStatement(new ReturnStatement()); } return(emitter); }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { var targetReference = getTargetReference(@class, MethodToOverride); emitter.CodeBuilder.AddStatement( new ExpressionStatement( new IfNullExpression(targetReference, IfNull(emitter.ReturnType), IfNotNull(targetReference)))); return(emitter); }
protected FieldReference BuildMethodInterceptorsField(ClassEmitter @class, MethodInfo method, INamingScope namingScope) { var methodInterceptors = @class.CreateField( namingScope.GetUniqueName(string.Format("interceptors_{0}", method.Name)), typeof(IInterceptor[]), false); #if !SILVERLIGHT @class.DefineCustomAttributeFor <XmlIgnoreAttribute>(methodInterceptors); #endif return(methodInterceptors); }
private NamingScope(INamingScope parent) { parentScope = parent; }
protected CompositeTypeContributor(INamingScope namingScope) { this.namingScope = namingScope; }
private AbstractTypeEmitter GetEmitter(ClassEmitter @class, Type[] interfaces, INamingScope namingScope, MethodInfo methodInfo) { var suggestedName = string.Format("Castle.Proxies.Invocations.{0}_{1}", methodInfo.DeclaringType.Name, methodInfo.Name); var uniqueName = namingScope.ParentScope.GetUniqueName(suggestedName); return(new ClassEmitter(@class.ModuleScope, uniqueName, GetBaseType(), interfaces, ClassEmitter.DefaultAttributes, forceUnsigned: @class.InStrongNamedModule == false)); }
protected virtual InterfaceProxyWithoutTargetContributor GetContributorForAdditionalInterfaces(INamingScope namingScope) { return new InterfaceProxyWithoutTargetContributor(namingScope, (c, m) => NullExpression.Instance) { Logger = Logger }; }
protected abstract MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, INamingScope namingScope);
public InterfaceProxyWithoutTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget) : base(namingScope) { getTargetExpression = getTarget; }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { InitOutParameters(emitter, MethodToOverride.GetParameters()); if (emitter.ReturnType == typeof(void)) { emitter.CodeBuilder.AddStatement(new ReturnStatement()); } else { emitter.CodeBuilder.AddStatement(new ReturnStatement(new DefaultValueExpression(emitter.ReturnType))); } return(emitter); }
public AbstractTypeEmitter Generate(ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { var emitter = GetEmitter(@class, namingScope); BuildConstructor(emitter); BuildInvokeMethod(emitter); return(emitter); }
public InterfaceProxyWithTargetInterfaceTargetContributor(Type proxyTargetType, bool allowChangeTarget, INamingScope namingScope) : base(proxyTargetType, allowChangeTarget, namingScope) { }
private Type GenerateType(string name, INamingScope namingScope) { IEnumerable <ITypeContributor> contributors; var implementedInterfaces = GetTypeImplementerMapping(out contributors, namingScope); var model = new MetaType(); // Collect methods foreach (var contributor in contributors) { contributor.CollectElementsToProxy(ProxyGenerationOptions.Hook, model); } ProxyGenerationOptions.Hook.MethodsInspected(); var emitter = BuildClassEmitter(name, targetType, implementedInterfaces); CreateFields(emitter); CreateTypeAttributes(emitter); // Constructor var cctor = GenerateStaticConstructor(emitter); var targetField = CreateTargetField(emitter); var constructorArguments = new List <FieldReference> { targetField }; foreach (var contributor in contributors) { contributor.Generate(emitter, ProxyGenerationOptions); // TODO: redo it if (contributor is MixinContributor) { constructorArguments.AddRange((contributor as MixinContributor).Fields); } } // constructor arguments var interceptorsField = emitter.GetField("__interceptors"); constructorArguments.Add(interceptorsField); var selector = emitter.GetField("__selector"); if (selector != null) { constructorArguments.Add(selector); } GenerateConstructors(emitter, targetType, constructorArguments.ToArray()); GenerateParameterlessConstructor(emitter, targetType, interceptorsField); // Complete type initializer code body CompleteInitCacheMethod(cctor.CodeBuilder); // Crosses fingers and build type var proxyType = emitter.BuildType(); InitializeStaticFields(proxyType); return(proxyType); }
protected virtual IEnumerable <Type> GetTypeImplementerMapping(out IEnumerable <ITypeContributor> contributors, INamingScope namingScope) { var methodsToSkip = new List <MethodInfo>(); var proxyInstance = new ClassProxyInstanceContributor(targetType, methodsToSkip, additionalInterfacesToProxy, ProxyTypeConstants.ClassWithTarget); // TODO: the trick with methodsToSkip is not very nice... var proxyTarget = new ClassProxyWithTargetTargetContributor(targetType, methodsToSkip, namingScope) { Logger = Logger }; IDictionary <Type, ITypeContributor> typeImplementerMapping = new Dictionary <Type, ITypeContributor>(); // Order of interface precedence: // 1. first target // target is not an interface so we do nothing var targetInterfaces = targetType.GetAllInterfaces(); // 2. then mixins var mixins = new MixinContributor(namingScope, false) { Logger = Logger }; if (ProxyGenerationOptions.HasMixins) { foreach (var mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfaces) { if (targetInterfaces.Contains(mixinInterface)) { // OK, so the target implements this interface. We now do one of two things: if (additionalInterfacesToProxy.Contains(mixinInterface) && typeImplementerMapping.ContainsKey(mixinInterface) == false) { AddMappingNoCheck(mixinInterface, proxyTarget, typeImplementerMapping); proxyTarget.AddInterfaceToProxy(mixinInterface); } // we do not intercept the interface mixins.AddEmptyInterface(mixinInterface); } else { if (!typeImplementerMapping.ContainsKey(mixinInterface)) { mixins.AddInterfaceToProxy(mixinInterface); AddMappingNoCheck(mixinInterface, mixins, typeImplementerMapping); } } } } var additionalInterfacesContributor = new InterfaceProxyWithoutTargetContributor(namingScope, (c, m) => NullExpression.Instance) { Logger = Logger }; // 3. then additional interfaces foreach (var @interface in additionalInterfacesToProxy) { if (targetInterfaces.Contains(@interface)) { if (typeImplementerMapping.ContainsKey(@interface)) { continue; } // we intercept the interface, and forward calls to the target type AddMappingNoCheck(@interface, proxyTarget, typeImplementerMapping); proxyTarget.AddInterfaceToProxy(@interface); } else if (ProxyGenerationOptions.MixinData.ContainsMixin(@interface) == false) { additionalInterfacesContributor.AddInterfaceToProxy(@interface); AddMapping(@interface, additionalInterfacesContributor, typeImplementerMapping); } } #if !SILVERLIGHT // 4. plus special interfaces if (targetType.IsSerializable) { AddMappingForISerializable(typeImplementerMapping, proxyInstance); } #endif try { AddMappingNoCheck(typeof(IProxyTargetAccessor), proxyInstance, typeImplementerMapping); } catch (ArgumentException) { HandleExplicitlyPassedProxyTargetAccessor(targetInterfaces, additionalInterfacesToProxy); } contributors = new List <ITypeContributor> { proxyTarget, mixins, additionalInterfacesContributor, proxyInstance }; return(typeImplementerMapping.Keys); }
public virtual void Generate(ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { foreach (var method in methods) { if (!method.Standalone) { continue; } ImplementMethod(method, @class, options, @class.CreateMethod, namingScope); } foreach (var property in properties) { ImplementProperty(@class, property, options, namingScope); } foreach (var @event in events) { ImplementEvent(@class, @event, options, namingScope); } }
public InterfaceProxyTargetContributor(Type proxyTargetType, bool canChangeTarget, INamingScope namingScope, ModuleScope scope) : base(namingScope, scope) { this.proxyTargetType = proxyTargetType; this.canChangeTarget = canChangeTarget; }
public override void Generate(ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { if (constructorContributor != null && registrar != null) { foreach (var statement in registrar.ConstructorStatements) { constructorContributor.AppendConstructorStatement(statement); } } base.Generate(@class, options, namingScope); }
protected override ITypeContributor AddMappingForTargetType(IDictionary <Type, ITypeContributor> typeImplementerMapping, Type proxyTargetType, ICollection <Type> targetInterfaces, ICollection <Type> additionalInterfaces, INamingScope namingScope) { var contributor = new InterfaceProxyWithTargetInterfaceTargetContributor( proxyTargetType, AllowChangeTarget, namingScope) { Logger = Logger }; foreach (var @interface in targetType.GetAllInterfaces()) { contributor.AddInterfaceToProxy(@interface); AddMappingNoCheck(@interface, contributor, typeImplementerMapping); } return(contributor); }
private Expression SetMethodInterceptors(ClassEmitter @class, INamingScope namingScope, MethodEmitter emitter, Expression proxiedMethodTokenExpression) { var selector = @class.GetField("__selector"); if(selector == null) { return null; } var methodInterceptorsField = BuildMethodInterceptorsField(@class, MethodToOverride, namingScope); var emptyInterceptors = new NewArrayExpression(0, typeof(IInterceptor)); var selectInterceptors = new MethodInvocationExpression(selector, InterceptorSelectorMethods.SelectInterceptors, new MethodInvocationExpression(null, TypeUtilMethods.GetTypeOrNull, getTargetExpression(@class, MethodToOverride)), proxiedMethodTokenExpression, interceptors.ToExpression()) { VirtualCall = true }; emitter.CodeBuilder.AddExpression( new IfNullExpression(methodInterceptorsField, new AssignStatement(methodInterceptorsField, new NullCoalescingOperatorExpression(selectInterceptors, emptyInterceptors)))); return methodInterceptorsField.ToExpression(); }
protected CompositeTypeContributor(INamingScope namingScope, ModuleScope scope) { this.scope = scope; this.namingScope = namingScope; }
protected virtual IEnumerable<Type> GetTypeImplementerMapping(Type[] interfaces, Type proxyTargetType, out IEnumerable<ITypeContributor> contributors, INamingScope namingScope) { IDictionary<Type, ITypeContributor> typeImplementerMapping = new Dictionary<Type, ITypeContributor>(); var mixins = new MixinContributor(namingScope, AllowChangeTarget) { Logger = Logger }; // Order of interface precedence: // 1. first target ICollection<Type> targetInterfaces = proxyTargetType.GetAllInterfaces(); ICollection<Type> additionalInterfaces = TypeUtil.GetAllInterfaces(interfaces); var target = AddMappingForTargetType(typeImplementerMapping, proxyTargetType, targetInterfaces, additionalInterfaces,namingScope); // 2. then mixins if (ProxyGenerationOptions.HasMixins) { foreach (var mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfaces) { if (targetInterfaces.Contains(mixinInterface)) { // OK, so the target implements this interface. We now do one of two things: if(additionalInterfaces.Contains(mixinInterface)) { // we intercept the interface, and forward calls to the target type AddMapping(mixinInterface, target, typeImplementerMapping); } // we do not intercept the interface mixins.AddEmptyInterface(mixinInterface); } else { if (!typeImplementerMapping.ContainsKey(mixinInterface)) { mixins.AddInterfaceToProxy(mixinInterface); typeImplementerMapping.Add(mixinInterface, mixins); } } } } var additionalInterfacesContributor = GetContributorForAdditionalInterfaces(namingScope); // 3. then additional interfaces foreach (var @interface in additionalInterfaces) { if(typeImplementerMapping.ContainsKey(@interface)) continue; if(ProxyGenerationOptions.MixinData.ContainsMixin(@interface)) continue; additionalInterfacesContributor.AddInterfaceToProxy(@interface); AddMappingNoCheck(@interface, additionalInterfacesContributor, typeImplementerMapping); } // 4. plus special interfaces var instance = new InterfaceProxyInstanceContributor(targetType, GeneratorType, interfaces); AddMappingForISerializable(typeImplementerMapping, instance); try { AddMappingNoCheck(typeof(IProxyTargetAccessor), instance, typeImplementerMapping); } catch (ArgumentException) { HandleExplicitlyPassedProxyTargetAccessor(targetInterfaces, additionalInterfaces); } contributors = new List<ITypeContributor> { target, additionalInterfacesContributor, mixins, instance }; return typeImplementerMapping.Keys; }
private Expression[] GetCtorArguments(ClassEmitter @class, INamingScope namingScope, Expression proxiedMethodTokenExpression, TypeReference[] dereferencedArguments) { var selector = @class.GetField("__selector"); if (selector != null) { return new[] { getTargetExpression(@class, MethodToOverride), SelfReference.Self.ToExpression(), interceptors.ToExpression(), proxiedMethodTokenExpression, new ReferencesToObjectArrayExpression(dereferencedArguments), selector.ToExpression(), new AddressOfReferenceExpression(BuildMethodInterceptorsField(@class, MethodToOverride, namingScope)) }; } return new[] { getTargetExpression(@class, MethodToOverride), SelfReference.Self.ToExpression(), interceptors.ToExpression(), proxiedMethodTokenExpression, new ReferencesToObjectArrayExpression(dereferencedArguments) }; }
protected virtual IEnumerable<Type> GetTypeImplementerMapping(Type[] interfaces, out IEnumerable<ITypeContributor> contributors, INamingScope namingScope) { var methodsToSkip = new List<MethodInfo>(); var proxyInstance = new ClassProxyInstanceContributor(targetType, methodsToSkip, interfaces, ProxyTypeConstants.Class); // TODO: the trick with methodsToSkip is not very nice... var proxyTarget = new ClassProxyTargetContributor(targetType, methodsToSkip, namingScope) { Logger = Logger }; IDictionary<Type, ITypeContributor> typeImplementerMapping = new Dictionary<Type, ITypeContributor>(); // Order of interface precedence: // 1. first target // target is not an interface so we do nothing var targetInterfaces = targetType.GetAllInterfaces(); var additionalInterfaces = TypeUtil.GetAllInterfaces(interfaces); // 2. then mixins var mixins = new MixinContributor(namingScope, false) { Logger = Logger }; if (ProxyGenerationOptions.HasMixins) { foreach (var mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfaces) { if (targetInterfaces.Contains(mixinInterface)) { // OK, so the target implements this interface. We now do one of two things: if (additionalInterfaces.Contains(mixinInterface) && typeImplementerMapping.ContainsKey(mixinInterface) == false) { AddMappingNoCheck(mixinInterface, proxyTarget, typeImplementerMapping); proxyTarget.AddInterfaceToProxy(mixinInterface); } // we do not intercept the interface mixins.AddEmptyInterface(mixinInterface); } else { if (!typeImplementerMapping.ContainsKey(mixinInterface)) { mixins.AddInterfaceToProxy(mixinInterface); AddMappingNoCheck(mixinInterface, mixins, typeImplementerMapping); } } } } var additionalInterfacesContributor = new InterfaceProxyWithoutTargetContributor(namingScope, (c, m) => NullExpression.Instance) { Logger = Logger }; // 3. then additional interfaces foreach (var @interface in additionalInterfaces) { if (targetInterfaces.Contains(@interface)) { if (typeImplementerMapping.ContainsKey(@interface)) { continue; } // we intercept the interface, and forward calls to the target type AddMappingNoCheck(@interface, proxyTarget, typeImplementerMapping); proxyTarget.AddInterfaceToProxy(@interface); } else if (ProxyGenerationOptions.MixinData.ContainsMixin(@interface) == false) { additionalInterfacesContributor.AddInterfaceToProxy(@interface); AddMapping(@interface, additionalInterfacesContributor, typeImplementerMapping); } } // 4. plus special interfaces #if FEATURE_SERIALIZATION if (targetType.IsSerializable) { AddMappingForISerializable(typeImplementerMapping, proxyInstance); } #endif try { AddMappingNoCheck(typeof(IProxyTargetAccessor), proxyInstance, typeImplementerMapping); } catch (ArgumentException) { HandleExplicitlyPassedProxyTargetAccessor(targetInterfaces, additionalInterfaces); } contributors = new List<ITypeContributor> { proxyTarget, mixins, additionalInterfacesContributor, proxyInstance }; return typeImplementerMapping.Keys; }
protected override InterfaceProxyWithoutTargetContributor GetContributorForAdditionalInterfaces(INamingScope namingScope) { return(new InterfaceProxyWithOptionalTargetContributor(namingScope, GetTargetExpression, GetTarget) { Logger = Logger }); }
public InterfaceProxyWithTargetInterfaceTargetContributor(Type proxyTargetType, bool allowChangeTarget, INamingScope namingScope, ModuleScope scope) : base(proxyTargetType, allowChangeTarget, namingScope, scope) { }
/// <summary> /// Gets the contributors for generating the type definition. /// </summary> /// <param name="interfaces">Additional interfaces to implement.</param> /// <param name="proxyTargetType">The target type for the proxy.</param> /// <param name="contributors">The list of contributors that will be used to generate the type.</param> /// <param name="namingScope">The proxy type naming scope.</param> /// <returns> /// The list of types being implemented. /// </returns> /// <remarks> /// <para> /// This version of the method basically does the same thing as the /// original/base implementation but with these key differences: /// </para> /// <list type="bullet"> /// <item> /// <term>No mixin support</term> /// <description> /// The original version of the method looks at the <see cref="Castle.DynamicProxy.Generators.BaseProxyGenerator.ProxyGenerationOptions"/> /// to see if there are any mixins to be added to the generated proxy. /// There is no need for mixin support in WCF service hosting so mixins /// aren't even checked for and won't be added. /// </description> /// </item> /// <item> /// <term>No additional interfaces</term> /// <description> /// The original version of the method goes through each of the additional /// interfaces that the are to be implemented, checks them against collisions /// with mixin definitions, and adds type mappings for the additional interfaces. /// The only interface that needs to be implemented for the WCF hosting /// proxy is the service interface, so all of that additional interface /// checking is skipped. /// </description> /// </item> /// <item> /// <term>Custom instance contributor used</term> /// <description> /// The original version of the method uses the /// <see cref="Castle.DynamicProxy.Contributors.InterfaceProxyInstanceContributor"/> /// as the code generator for the proxy type. Unfortunately, that contributor /// copies over all non-inherited attributes on the interface including /// the <see cref="System.ServiceModel.ServiceContractAttribute"/>. The /// concrete proxy type can't have that attribute because the interface /// already has it, so WCF hosting dies. This version of the method uses /// the <see cref="Autofac.Multitenant.Wcf.DynamicProxy.IgnoreAttributeInterfaceProxyInstanceContributor"/> /// which does not copy over non-inherited attributes. /// </description> /// </item> /// </list> /// </remarks> /// <seealso cref="Autofac.Multitenant.Wcf.DynamicProxy.IgnoreAttributeInterfaceProxyInstanceContributor"/> protected override IEnumerable <Type> GetTypeImplementerMapping(Type[] interfaces, Type proxyTargetType, out IEnumerable <ITypeContributor> contributors, INamingScope namingScope) { var typeImplementerMapping = new Dictionary <Type, ITypeContributor>(); var allInterfaces = TypeUtil.GetAllInterfaces(new[] { proxyTargetType }); var additionalInterfaces = TypeUtil.GetAllInterfaces(interfaces); var implementer = AddMappingForTargetType(typeImplementerMapping, proxyTargetType, allInterfaces, additionalInterfaces, namingScope); var instance = new IgnoreAttributeInterfaceProxyInstanceContributor(targetType, GeneratorType, interfaces); AddMappingForISerializable(typeImplementerMapping, instance); try { AddMappingNoCheck(typeof(IProxyTargetAccessor), instance, typeImplementerMapping); } catch (ArgumentException) { HandleExplicitlyPassedProxyTargetAccessor(allInterfaces, additionalInterfaces); } contributors = new List <ITypeContributor> { implementer, instance }; return(typeImplementerMapping.Keys); }
private AbstractTypeEmitter GetEmitter(ClassEmitter @class, Type[] interfaces, INamingScope namingScope, MethodInfo methodInfo) { var suggestedName = string.Format("Hermit.Proxies.Invocations.{0}_{1}", methodInfo.DeclaringType.Name, methodInfo.Name); var uniqueName = namingScope.ParentScope.GetUniqueName(suggestedName); return(new ClassEmitter(@class.ModuleScope, uniqueName, GetBaseType(), interfaces)); }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options,INamingScope namingScope) { var invocationType = invocation; Trace.Assert(MethodToOverride.IsGenericMethod == invocationType.IsGenericTypeDefinition); Type[] genericMethodArgs = Type.EmptyTypes; ConstructorInfo constructor = invocation.GetConstructors()[0]; Expression proxiedMethodTokenExpression; if (MethodToOverride.IsGenericMethod) { // bind generic method arguments to invocation's type arguments genericMethodArgs = emitter.MethodBuilder.GetGenericArguments(); invocationType = invocationType.MakeGenericType(genericMethodArgs); constructor = TypeBuilder.GetConstructor(invocationType, constructor); // Not in the cache: generic method proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericMethodArgs)); } else { var proxiedMethodToken = @class.CreateStaticField(namingScope.GetUniqueName("token_" + MethodToOverride.Name), typeof(MethodInfo)); @class.ClassConstructor.CodeBuilder.AddStatement(new AssignStatement(proxiedMethodToken, new MethodTokenExpression(MethodToOverride))); proxiedMethodTokenExpression = proxiedMethodToken.ToExpression(); } var dereferencedArguments = IndirectReference.WrapIfByRef(emitter.Arguments); var ctorArguments = GetCtorArguments(@class, namingScope, proxiedMethodTokenExpression, dereferencedArguments); var invocationLocal = emitter.CodeBuilder.DeclareLocal(invocationType); emitter.CodeBuilder.AddStatement(new AssignStatement(invocationLocal, new NewInstanceExpression(constructor, ctorArguments))); if (MethodToOverride.ContainsGenericParameters) { EmitLoadGenricMethodArguments(emitter, MethodToOverride.MakeGenericMethod(genericMethodArgs), invocationLocal); } emitter.CodeBuilder.AddStatement( new ExpressionStatement(new MethodInvocationExpression(invocationLocal, InvocationMethods.Proceed))); GeneratorUtil.CopyOutAndRefParameters(dereferencedArguments, invocationLocal, MethodToOverride, emitter); if (MethodToOverride.ReturnType != typeof(void)) { // Emit code to return with cast from ReturnValue var getRetVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue); emitter.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(emitter.ReturnType, getRetVal))); } else { emitter.CodeBuilder.AddStatement(new ReturnStatement()); } return emitter; }
public AbstractTypeEmitter Generate(ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { var methodInfo = method.Method; var interfaces = new Type[0]; if (canChangeTarget) { interfaces = new[] { typeof(IChangeProxyTarget) }; } var invocation = GetEmitter(@class, interfaces, namingScope, methodInfo); // invocation only needs to mirror the generic parameters of the MethodInfo // targetType cannot be a generic type definition (YET!) invocation.CopyGenericParametersFromMethod(methodInfo); CreateConstructor(invocation, options); var targetField = GetTargetReference(); if (canChangeTarget) { ImplementChangeProxyTargetInterface(@class, invocation, targetField); } ImplemementInvokeMethodOnTarget(invocation, methodInfo.GetParameters(), targetField, callback); invocation.DefineCustomAttribute <SerializableAttribute>(); return(invocation); }
protected virtual IEnumerable <Type> GetTypeImplementerMapping(Type[] interfaces, Type proxyTargetType, out IEnumerable <ITypeContributor> contributors, INamingScope namingScope) { IDictionary <Type, ITypeContributor> typeImplementerMapping = new Dictionary <Type, ITypeContributor>(); var mixins = new MixinContributor(namingScope, AllowChangeTarget) { Logger = Logger }; // Order of interface precedence: // 1. first target var targetInterfaces = proxyTargetType.GetAllInterfaces(); var additionalInterfaces = TypeUtil.GetAllInterfaces(interfaces); var target = AddMappingForTargetType(typeImplementerMapping, proxyTargetType, targetInterfaces, additionalInterfaces, namingScope); // 2. then mixins if (ProxyGenerationOptions.HasMixins) { foreach (var mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfaces) { if (targetInterfaces.Contains(mixinInterface)) { // OK, so the target implements this interface. We now do one of two things: if (additionalInterfaces.Contains(mixinInterface)) { // we intercept the interface, and forward calls to the target type AddMapping(mixinInterface, target, typeImplementerMapping); } // we do not intercept the interface mixins.AddEmptyInterface(mixinInterface); } else { if (!typeImplementerMapping.ContainsKey(mixinInterface)) { mixins.AddInterfaceToProxy(mixinInterface); typeImplementerMapping.Add(mixinInterface, mixins); } } } } var additionalInterfacesContributor = GetContributorForAdditionalInterfaces(namingScope); // 3. then additional interfaces foreach (var @interface in additionalInterfaces) { if (typeImplementerMapping.ContainsKey(@interface)) { continue; } if (ProxyGenerationOptions.MixinData.ContainsMixin(@interface)) { continue; } additionalInterfacesContributor.AddInterfaceToProxy(@interface); AddMappingNoCheck(@interface, additionalInterfacesContributor, typeImplementerMapping); } // 4. plus special interfaces var instance = new InterfaceProxyInstanceContributor(targetType, GeneratorType, interfaces); #if FEATURE_SERIALIZATION AddMappingForISerializable(typeImplementerMapping, instance); #endif try { AddMappingNoCheck(typeof(IProxyTargetAccessor), instance, typeImplementerMapping); } catch (ArgumentException) { HandleExplicitlyPassedProxyTargetAccessor(targetInterfaces, additionalInterfaces); } contributors = new List <ITypeContributor> { target, additionalInterfacesContributor, mixins, instance }; return(typeImplementerMapping.Keys); }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, INamingScope namingScope) { var invocationType = invocation; var genericArguments = Type.EmptyTypes; var constructor = invocation.GetConstructors()[0]; IExpression proxiedMethodTokenExpression; if (MethodToOverride.IsGenericMethod) { // Not in the cache: generic method genericArguments = emitter.MethodBuilder.GetGenericArguments(); proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericArguments)); if (invocationType.IsGenericTypeDefinition) { // bind generic method arguments to invocation's type arguments invocationType = invocationType.MakeGenericType(genericArguments); constructor = TypeBuilder.GetConstructor(invocationType, constructor); } } else { var proxiedMethodToken = @class.CreateStaticField(namingScope.GetUniqueName("token_" + MethodToOverride.Name), typeof(MethodInfo)); @class.ClassConstructor.CodeBuilder.AddStatement(new AssignStatement(proxiedMethodToken, new MethodTokenExpression(MethodToOverride))); proxiedMethodTokenExpression = proxiedMethodToken; } var methodInterceptors = SetMethodInterceptors(@class, namingScope, emitter, proxiedMethodTokenExpression); var dereferencedArguments = IndirectReference.WrapIfByRef(emitter.Arguments); var hasByRefArguments = HasByRefArguments(emitter.Arguments); var arguments = GetCtorArguments(@class, proxiedMethodTokenExpression, dereferencedArguments, methodInterceptors); var ctorArguments = ModifyArguments(@class, arguments); var invocationLocal = emitter.CodeBuilder.DeclareLocal(invocationType); emitter.CodeBuilder.AddStatement(new AssignStatement(invocationLocal, new NewInstanceExpression(constructor, ctorArguments))); if (MethodToOverride.ContainsGenericParameters) { EmitLoadGenericMethodArguments(emitter, MethodToOverride.MakeGenericMethod(genericArguments), invocationLocal); } if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new TryStatement()); } var proceed = new MethodInvocationExpression(invocationLocal, InvocationMethods.Proceed); emitter.CodeBuilder.AddStatement(proceed); if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new FinallyStatement()); } GeneratorUtil.CopyOutAndRefParameters(dereferencedArguments, invocationLocal, MethodToOverride, emitter); if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new EndExceptionBlockStatement()); } if (MethodToOverride.ReturnType != typeof(void)) { var getRetVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue); // Emit code to ensure a value type return type is not null, otherwise the cast will cause a null-deref if (emitter.ReturnType.IsValueType && !emitter.ReturnType.IsNullableType()) { LocalReference returnValue = emitter.CodeBuilder.DeclareLocal(typeof(object)); emitter.CodeBuilder.AddStatement(new AssignStatement(returnValue, getRetVal)); emitter.CodeBuilder.AddStatement(new IfNullExpression(returnValue, new ThrowStatement(typeof(InvalidOperationException), "Interceptors failed to set a return value, or swallowed the exception thrown by the target"))); } // Emit code to return with cast from ReturnValue emitter.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(emitter.ReturnType, getRetVal))); } else { emitter.CodeBuilder.AddStatement(new ReturnStatement()); } return(emitter); }
protected virtual Type GenerateType(string typeName, Type proxyTargetType, Type[] interfaces, INamingScope namingScope) { var allInterfaces = GetTypeImplementerMapping(interfaces, proxyTargetType, out IEnumerable <ITypeContributor> contributors, namingScope); var baseType = Init(typeName, out ClassEmitter emitter, proxyTargetType, out FieldReference interceptorsField, allInterfaces); var model = new MetaType(); // Collect methods foreach (var contributor in contributors) { contributor.CollectElementsToProxy(ProxyGenerationOptions.Hook, model); } ProxyGenerationOptions.Hook.MethodsInspected(); // Constructor var cctor = GenerateStaticConstructor(emitter); var ctorArguments = new List <FieldReference>(); foreach (var contributor in contributors) { contributor.Generate(emitter, ProxyGenerationOptions); // TODO: redo it if (contributor is MixinContributor) { ctorArguments.AddRange((contributor as MixinContributor).Fields); } } ctorArguments.Add(interceptorsField); ctorArguments.Add(targetField); var selector = emitter.GetField("__selector"); if (selector != null) { ctorArguments.Add(selector); } GenerateConstructors(emitter, baseType, ctorArguments.ToArray()); // Complete type initializer code body CompleteInitCacheMethod(cctor.CodeBuilder); // Crosses fingers and build type var generatedType = emitter.BuildType(); InitializeStaticFields(generatedType); return(generatedType); }