diff --git a/src/Castle.Core/DynamicProxy/Generators/BaseClassProxyGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/BaseClassProxyGenerator.cs index db25bcbbfa..638f32131e 100644 --- a/src/Castle.Core/DynamicProxy/Generators/BaseClassProxyGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/BaseClassProxyGenerator.cs @@ -100,21 +100,24 @@ protected sealed override Type GenerateType(string name, INamingScope namingScop private IEnumerable GetTypeImplementerMapping(out IEnumerable contributors, INamingScope namingScope) { - var methodsToSkip = new List(); - var proxyInstance = GetProxyInstanceContributor(methodsToSkip); - // TODO: the trick with methodsToSkip is not very nice... - var proxyTarget = GetProxyTargetContributor(methodsToSkip, namingScope); - IDictionary typeImplementerMapping = new Dictionary(); + var contributorsList = new List(capacity: 4); + var methodsToSkip = new List(); // TODO: the trick with methodsToSkip is not very nice... + var targetInterfaces = targetType.GetAllInterfaces(); + var typeImplementerMapping = new Dictionary(); // Order of interface precedence: + // 1. first target // target is not an interface so we do nothing + var targetContributor = GetProxyTargetContributor(methodsToSkip, namingScope); + contributorsList.Add(targetContributor); - var targetInterfaces = targetType.GetAllInterfaces(); // 2. then mixins - var mixins = new MixinContributor(namingScope, false) { Logger = Logger }; if (ProxyGenerationOptions.HasMixins) { + var mixinContributor = new MixinContributor(namingScope, false) { Logger = Logger }; + contributorsList.Add(mixinContributor); + foreach (var mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfaces) { if (targetInterfaces.Contains(mixinInterface)) @@ -123,68 +126,69 @@ private IEnumerable GetTypeImplementerMapping(out IEnumerable NullExpression.Instance) - { Logger = Logger }; + // 3. then additional interfaces - foreach (var @interface in interfaces) + if (interfaces.Length > 0) { - if (targetInterfaces.Contains(@interface)) + var additionalInterfacesContributor = new InterfaceProxyWithoutTargetContributor(namingScope, (c, m) => NullExpression.Instance) { Logger = Logger }; + contributorsList.Add(additionalInterfacesContributor); + + foreach (var @interface in interfaces) { - if (typeImplementerMapping.ContainsKey(@interface)) + if (targetInterfaces.Contains(@interface)) { - continue; - } + 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); + // we intercept the interface, and forward calls to the target type + AddMappingNoCheck(@interface, targetContributor, typeImplementerMapping); + targetContributor.AddInterfaceToProxy(@interface); + } + else if (ProxyGenerationOptions.MixinData.ContainsMixin(@interface) == false) + { + additionalInterfacesContributor.AddInterfaceToProxy(@interface); + AddMapping(@interface, additionalInterfacesContributor, typeImplementerMapping); + } } } + // 4. plus special interfaces + var instanceContributor = GetProxyInstanceContributor(methodsToSkip); + contributorsList.Add(instanceContributor); #if FEATURE_SERIALIZATION if (targetType.IsSerializable) { - AddMappingForISerializable(typeImplementerMapping, proxyInstance); + AddMappingForISerializable(typeImplementerMapping, instanceContributor); } #endif try { - AddMappingNoCheck(typeof(IProxyTargetAccessor), proxyInstance, typeImplementerMapping); + AddMappingNoCheck(typeof(IProxyTargetAccessor), instanceContributor, typeImplementerMapping); } catch (ArgumentException) { HandleExplicitlyPassedProxyTargetAccessor(targetInterfaces); } - contributors = new List - { - proxyTarget, - mixins, - additionalInterfacesContributor, - proxyInstance - }; + contributors = contributorsList; return typeImplementerMapping.Keys; } diff --git a/src/Castle.Core/DynamicProxy/Generators/BaseInterfaceProxyGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/BaseInterfaceProxyGenerator.cs index 772a109165..cab25c0207 100644 --- a/src/Castle.Core/DynamicProxy/Generators/BaseInterfaceProxyGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/BaseInterfaceProxyGenerator.cs @@ -146,16 +146,21 @@ protected virtual IEnumerable GetTypeImplementerMapping(Type proxyTargetTy out IEnumerable contributors, INamingScope namingScope) { - IDictionary typeImplementerMapping = new Dictionary(); - var mixins = new MixinContributor(namingScope, AllowChangeTarget) { Logger = Logger }; + var contributorsList = new List(capacity: 4); + var targetInterfaces = proxyTargetType.GetAllInterfaces(); + var typeImplementerMapping = new Dictionary(); + // Order of interface precedence: // 1. first target - var targetInterfaces = proxyTargetType.GetAllInterfaces(); - var target = AddMappingForTargetType(typeImplementerMapping, proxyTargetType, targetInterfaces, namingScope); + var targetContributor = AddMappingForTargetType(typeImplementerMapping, proxyTargetType, targetInterfaces, namingScope); + contributorsList.Add(targetContributor); // 2. then mixins if (ProxyGenerationOptions.HasMixins) { + var mixinContributor = new MixinContributor(namingScope, AllowChangeTarget) { Logger = Logger }; + contributorsList.Add(mixinContributor); + foreach (var mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfaces) { if (targetInterfaces.Contains(mixinInterface)) @@ -164,60 +169,60 @@ protected virtual IEnumerable GetTypeImplementerMapping(Type proxyTargetTy if (interfaces.Contains(mixinInterface)) { // we intercept the interface, and forward calls to the target type - AddMapping(mixinInterface, target, typeImplementerMapping); + AddMapping(mixinInterface, targetContributor, typeImplementerMapping); } // we do not intercept the interface - mixins.AddEmptyInterface(mixinInterface); + mixinContributor.AddEmptyInterface(mixinInterface); } else { if (!typeImplementerMapping.ContainsKey(mixinInterface)) { - mixins.AddInterfaceToProxy(mixinInterface); - typeImplementerMapping.Add(mixinInterface, mixins); + mixinContributor.AddInterfaceToProxy(mixinInterface); + typeImplementerMapping.Add(mixinInterface, mixinContributor); } } } } - var additionalInterfacesContributor = GetContributorForAdditionalInterfaces(namingScope); // 3. then additional interfaces - foreach (var @interface in interfaces) + if (interfaces.Length > 0) { - if (typeImplementerMapping.ContainsKey(@interface)) - { - continue; - } - if (ProxyGenerationOptions.MixinData.ContainsMixin(@interface)) + var additionalInterfacesContributor = GetContributorForAdditionalInterfaces(namingScope); + contributorsList.Add(additionalInterfacesContributor); + + foreach (var @interface in interfaces) { - continue; - } + if (typeImplementerMapping.ContainsKey(@interface)) + { + continue; + } + if (ProxyGenerationOptions.MixinData.ContainsMixin(@interface)) + { + continue; + } - additionalInterfacesContributor.AddInterfaceToProxy(@interface); - AddMappingNoCheck(@interface, additionalInterfacesContributor, typeImplementerMapping); + additionalInterfacesContributor.AddInterfaceToProxy(@interface); + AddMappingNoCheck(@interface, additionalInterfacesContributor, typeImplementerMapping); + } } // 4. plus special interfaces - var instance = new InterfaceProxyInstanceContributor(targetType, GeneratorType, interfaces); + var instanceContributor = new InterfaceProxyInstanceContributor(targetType, GeneratorType, interfaces); + contributorsList.Add(instanceContributor); #if FEATURE_SERIALIZATION - AddMappingForISerializable(typeImplementerMapping, instance); + AddMappingForISerializable(typeImplementerMapping, instanceContributor); #endif try { - AddMappingNoCheck(typeof(IProxyTargetAccessor), instance, typeImplementerMapping); + AddMappingNoCheck(typeof(IProxyTargetAccessor), instanceContributor, typeImplementerMapping); } catch (ArgumentException) { HandleExplicitlyPassedProxyTargetAccessor(targetInterfaces); } - contributors = new List - { - target, - additionalInterfacesContributor, - mixins, - instance - }; + contributors = contributorsList; return typeImplementerMapping.Keys; }