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; }
protected virtual IEnumerable<Type> GetTypeImplementerMapping(out IEnumerable<ITypeContributor> contributors, INamingScope namingScope) { var methodsToSkip = new List<MethodInfo>(); var proxyInstance = new ClassProxyInstanceContributor(targetType, methodsToSkip, additionalInterfacesToProxy); // TODO: the trick with methodsToSkip is not very nice... var proxyTarget = new ClassProxyWithTargetTargetContributor(targetType, methodsToSkip, namingScope, this.Scope) { 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, Scope, 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, Scope, (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); } } try { AddMappingNoCheck(typeof(IProxyTargetAccessor), proxyInstance, typeImplementerMapping); } catch (ArgumentException) { HandleExplicitlyPassedProxyTargetAccessor(targetInterfaces, additionalInterfacesToProxy); } contributors = new List<ITypeContributor> { proxyTarget, mixins, additionalInterfacesContributor, proxyInstance }; return typeImplementerMapping.Keys; }