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 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; }