diff --git a/CHANGELOG.md b/CHANGELOG.md index 68dfe004c6..41066c123a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Enhancements: - .NET Standard 2.0 and 2.1 support (@lg2de, #485) - Non-intercepted methods on a class proxy with target are now forwarded to the target (@stakx, #571) - Significant performance improvements with proxy type generation for interface proxies without target. (Up until now, DynamicProxy generated a separate `IInvocation` implementation type for every single proxied method – it is now able to reuse a single predefined type in many cases, thereby reducing the total amount of dynamic type generation.) (@stakx, #573) +- `AttributesToAvoidReplicating` has been converted from a static class to a collection property on `ProxyGenerationOptions` (@stakx, #575) Bugfixes: - Proxying certain `[Serializable]` classes produces proxy types that fail PEVerify test (@stakx, #367) diff --git a/ref/Castle.Core-net45.cs b/ref/Castle.Core-net45.cs index f4914b2c7b..ea14b816ac 100644 --- a/ref/Castle.Core-net45.cs +++ b/ref/Castle.Core-net45.cs @@ -2653,6 +2653,7 @@ public class ProxyGenerationOptions : System.Runtime.Serialization.ISerializable public ProxyGenerationOptions() { } public ProxyGenerationOptions(Castle.DynamicProxy.IProxyGenerationHook hook) { } public System.Collections.Generic.IList AdditionalAttributes { get; } + public System.Collections.Generic.ISet AttributesToAvoidReplicating { get; } public System.Type BaseTypeForInterfaceProxy { get; set; } public bool HasMixins { get; } public Castle.DynamicProxy.IProxyGenerationHook Hook { get; set; } @@ -2758,15 +2759,6 @@ protected virtual void PostProceed(Castle.DynamicProxy.IInvocation invocation) { protected virtual void PreProceed(Castle.DynamicProxy.IInvocation invocation) { } } } -namespace Castle.DynamicProxy.Generators -{ - public static class AttributesToAvoidReplicating - { - public static void Add(System.Type attribute) { } - public static void Add() { } - public static bool Contains(System.Type attribute) { } - } -} namespace Castle.DynamicProxy.Internal { public abstract class CompositionInvocation : Castle.DynamicProxy.AbstractInvocation diff --git a/ref/Castle.Core-netstandard2.0.cs b/ref/Castle.Core-netstandard2.0.cs index e2d8604e8f..c92c3c40bc 100644 --- a/ref/Castle.Core-netstandard2.0.cs +++ b/ref/Castle.Core-netstandard2.0.cs @@ -2608,6 +2608,7 @@ public class ProxyGenerationOptions public ProxyGenerationOptions() { } public ProxyGenerationOptions(Castle.DynamicProxy.IProxyGenerationHook hook) { } public System.Collections.Generic.IList AdditionalAttributes { get; } + public System.Collections.Generic.ISet AttributesToAvoidReplicating { get; } public System.Type BaseTypeForInterfaceProxy { get; set; } public bool HasMixins { get; } public Castle.DynamicProxy.IProxyGenerationHook Hook { get; set; } @@ -2711,15 +2712,6 @@ protected virtual void PostProceed(Castle.DynamicProxy.IInvocation invocation) { protected virtual void PreProceed(Castle.DynamicProxy.IInvocation invocation) { } } } -namespace Castle.DynamicProxy.Generators -{ - public static class AttributesToAvoidReplicating - { - public static void Add(System.Type attribute) { } - public static void Add() { } - public static bool Contains(System.Type attribute) { } - } -} namespace Castle.DynamicProxy.Internal { public abstract class CompositionInvocation : Castle.DynamicProxy.AbstractInvocation diff --git a/ref/Castle.Core-netstandard2.1.cs b/ref/Castle.Core-netstandard2.1.cs index 00e2896aa3..dfc8be04c4 100644 --- a/ref/Castle.Core-netstandard2.1.cs +++ b/ref/Castle.Core-netstandard2.1.cs @@ -2608,6 +2608,7 @@ public class ProxyGenerationOptions public ProxyGenerationOptions() { } public ProxyGenerationOptions(Castle.DynamicProxy.IProxyGenerationHook hook) { } public System.Collections.Generic.IList AdditionalAttributes { get; } + public System.Collections.Generic.ISet AttributesToAvoidReplicating { get; } public System.Type BaseTypeForInterfaceProxy { get; set; } public bool HasMixins { get; } public Castle.DynamicProxy.IProxyGenerationHook Hook { get; set; } @@ -2711,15 +2712,6 @@ protected virtual void PostProceed(Castle.DynamicProxy.IInvocation invocation) { protected virtual void PreProceed(Castle.DynamicProxy.IInvocation invocation) { } } } -namespace Castle.DynamicProxy.Generators -{ - public static class AttributesToAvoidReplicating - { - public static void Add(System.Type attribute) { } - public static void Add() { } - public static bool Contains(System.Type attribute) { } - } -} namespace Castle.DynamicProxy.Internal { public abstract class CompositionInvocation : Castle.DynamicProxy.AbstractInvocation diff --git a/src/Castle.Core.Tests/DynamicProxy.Tests/AttributesToAvoidReplicatingTestCase.cs b/src/Castle.Core.Tests/DynamicProxy.Tests/AttributesToAvoidReplicatingTestCase.cs index e2a084ef06..61711bc9e9 100644 --- a/src/Castle.Core.Tests/DynamicProxy.Tests/AttributesToAvoidReplicatingTestCase.cs +++ b/src/Castle.Core.Tests/DynamicProxy.Tests/AttributesToAvoidReplicatingTestCase.cs @@ -19,7 +19,6 @@ namespace Castle.DynamicProxy.Tests using System.Reflection; using System.Security.Permissions; - using Castle.DynamicProxy.Generators; using Castle.DynamicProxy.Tests.Classes; using NUnit.Framework; @@ -28,26 +27,19 @@ namespace Castle.DynamicProxy.Tests public class AttributesToAvoidReplicatingTestCase : BasePEVerifyTestCase { [Test] - public void After_adding_attribute_must_be_listed_as_contained() - { - AttributesToAvoidReplicating.Add(); - bool contains = AttributesToAvoidReplicating.Contains(typeof(string)); - Assert.IsTrue(contains); - } - - [Test] - public void After_adding_attribute_must_still_contain_original_attributes() + public void NonInheritableAttribute_should_be_replicated_as_it_is_not_inherited() { - AttributesToAvoidReplicating.Add(); - bool contains = AttributesToAvoidReplicating.Contains(typeof(System.Runtime.InteropServices.ComImportAttribute)); - Assert.IsTrue(contains); + var proxy = generator.CreateClassProxy(); + Assert.AreEqual(1, AttributeCount(proxy)); } [Test] - public void NonInheritableAttribute_should_be_replicated_as_it_is_not_inherited() + public void NonInheritableAttribute_can_be_suppressed_via_AttributesToAvoidReplicating() { - var proxy = generator.CreateClassProxy(); - Assert.AreEqual(1, AttributeCount(proxy)); + var options = new ProxyGenerationOptions(); + options.AttributesToAvoidReplicating.Add(typeof(NonInheritableAttribute)); + var proxy = generator.CreateClassProxy(options); + Assert.AreEqual(0, AttributeCount(proxy)); } [NonInheritable] diff --git a/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs b/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs index 62d46e1697..d8a9ebe54e 100644 --- a/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs +++ b/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs @@ -27,7 +27,8 @@ public class ClassEmitterTestCase : BasePEVerifyTestCase [Test] public void AutomaticDefaultConstructorGeneration() { - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "Foo", typeof (object), Type.EmptyTypes); + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "Foo", typeof (object), Type.EmptyTypes); Type t = emitter.BuildType(); Activator.CreateInstance(t); } @@ -35,7 +36,8 @@ public void AutomaticDefaultConstructorGeneration() [Test] public void AutomaticDefaultConstructorGenerationWithClosedGenericType() { - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "Foo", typeof (List), + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "Foo", typeof (List), Type.EmptyTypes); Type t = emitter.BuildType(); Activator.CreateInstance(t); @@ -44,7 +46,8 @@ public void AutomaticDefaultConstructorGenerationWithClosedGenericType() [Test] public void StaticMethodArguments() { - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "Foo", typeof (List), + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "Foo", typeof (List), Type.EmptyTypes); MethodEmitter methodEmitter = emitter.CreateMethod("StaticMethod", MethodAttributes.Public | MethodAttributes.Static, typeof (string), typeof (string)); @@ -56,7 +59,8 @@ public void StaticMethodArguments() [Test] public void InstanceMethodArguments() { - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "Foo", typeof (List), + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "Foo", typeof (List), Type.EmptyTypes); MethodEmitter methodEmitter = emitter.CreateMethod("InstanceMethod", MethodAttributes.Public, typeof (string), typeof (string)); @@ -70,7 +74,8 @@ public void InstanceMethodArguments() public void ForceUnsignedFalseWithSignedTypes() { const bool shouldBeSigned = true; - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "Foo", typeof (object), Type.EmptyTypes, + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "Foo", typeof (object), Type.EmptyTypes, TypeAttributes.Public, false); Type t = emitter.BuildType(); Assert.AreEqual(shouldBeSigned, StrongNameUtil.IsAssemblySigned(t.Assembly)); @@ -79,7 +84,8 @@ public void ForceUnsignedFalseWithSignedTypes() [Test] public void ForceUnsignedTrueWithSignedTypes() { - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "Foo", typeof (object), Type.EmptyTypes, + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "Foo", typeof (object), Type.EmptyTypes, TypeAttributes.Public, true); Type t = emitter.BuildType(); Assert.IsFalse(StrongNameUtil.IsAssemblySigned(t.Assembly)); @@ -88,7 +94,8 @@ public void ForceUnsignedTrueWithSignedTypes() [Test] public void CreateFieldWithAttributes() { - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "Foo", typeof (object), Type.EmptyTypes); + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "Foo", typeof (object), Type.EmptyTypes); emitter.CreateField("myField", typeof (string), FieldAttributes.FamANDAssem | FieldAttributes.InitOnly); Type t = emitter.BuildType(); FieldInfo field = t.GetField("myField", BindingFlags.NonPublic | BindingFlags.Instance); @@ -99,7 +106,8 @@ public void CreateFieldWithAttributes() [Test] public void CreateStaticFieldWithAttributes() { - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "Foo", typeof (object), Type.EmptyTypes); + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "Foo", typeof (object), Type.EmptyTypes); emitter.CreateStaticField("myField", typeof (string), FieldAttributes.FamANDAssem | FieldAttributes.InitOnly); Type t = emitter.BuildType(); FieldInfo field = t.GetField("myField", BindingFlags.NonPublic | BindingFlags.Static); @@ -110,7 +118,8 @@ public void CreateStaticFieldWithAttributes() [Test] public void UsingClassEmitterForInterfaces() { - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public, false); emitter.CreateMethod("MyMethod", MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual, typeof(void), Type.EmptyTypes); @@ -124,7 +133,8 @@ public void UsingClassEmitterForInterfaces() public void NoBaseTypeForInterfaces() { DisableVerification(); - ClassEmitter emitter = new ClassEmitter (generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public, false); Assert.Throws(delegate { @@ -138,7 +148,8 @@ public void NoBaseTypeForInterfaces() public void NoDefaultCtorForInterfaces() { DisableVerification(); - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public, false); Assert.Throws(delegate { @@ -150,7 +161,8 @@ public void NoDefaultCtorForInterfaces() public void NoCustomCtorForInterfaces() { DisableVerification(); - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter emitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public, false); Assert.Throws(delegate { @@ -161,9 +173,10 @@ public void NoCustomCtorForInterfaces() [Test] public void NestedInterface() { - ClassEmitter outerEmitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "IOuter", null, Type.EmptyTypes, + var context = new ProxyGenerationContext(ProxyGenerationOptions.Default); + ClassEmitter outerEmitter = new ClassEmitter(context, generator.ProxyBuilder.ModuleScope, "IOuter", null, Type.EmptyTypes, TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public, false); - NestedClassEmitter innerEmitter = new NestedClassEmitter(outerEmitter, "IInner", + NestedClassEmitter innerEmitter = new NestedClassEmitter(context, outerEmitter, "IInner", TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.NestedPublic, null, Type.EmptyTypes); innerEmitter.CreateMethod("MyMethod", MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual, typeof(void), Type.EmptyTypes); diff --git a/src/Castle.Core/DynamicProxy/Contributors/ClassMembersCollector.cs b/src/Castle.Core/DynamicProxy/Contributors/ClassMembersCollector.cs index 1200cdae51..6047bab356 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/ClassMembersCollector.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/ClassMembersCollector.cs @@ -21,19 +21,19 @@ namespace Castle.DynamicProxy.Contributors internal class ClassMembersCollector : MembersCollector { - public ClassMembersCollector(Type targetType) - : base(targetType) + public ClassMembersCollector(ProxyGenerationContext context, Type targetType) + : base(context, targetType) { } - protected override MetaMethod GetMethodToGenerate(MethodInfo method, IProxyGenerationHook hook, bool isStandalone) + protected override MetaMethod GetMethodToGenerate(MethodInfo method, bool isStandalone) { if (ProxyUtil.IsAccessibleMethod(method) == false) { return null; } - var accepted = AcceptMethod(method, true, hook); + var accepted = AcceptMethod(method, true); if (!accepted && !method.IsAbstract) { //we don't need to do anything... diff --git a/src/Castle.Core/DynamicProxy/Contributors/ClassProxySerializableContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/ClassProxySerializableContributor.cs index c5c58f3931..e37a304582 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/ClassProxySerializableContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/ClassProxySerializableContributor.cs @@ -41,7 +41,7 @@ public ClassProxySerializableContributor(Type targetType, Type[] interfaces, str Debug.Assert(targetType.IsSerializable, "This contributor is intended for serializable types only."); } - public override void CollectElementsToProxy(IProxyGenerationHook hook, MetaType model) + public override void CollectElementsToProxy(MetaType model) { delegateToBaseGetObjectData = VerifyIfBaseImplementsGetObjectData(targetType, model, out var getObjectData); diff --git a/src/Castle.Core/DynamicProxy/Contributors/ClassProxyTargetContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/ClassProxyTargetContributor.cs index 6b72d993a3..f9ffd3fd3b 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/ClassProxyTargetContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/ClassProxyTargetContributor.cs @@ -31,21 +31,21 @@ internal class ClassProxyTargetContributor : CompositeTypeContributor { private readonly Type targetType; - public ClassProxyTargetContributor(Type targetType, INamingScope namingScope) - : base(namingScope) + public ClassProxyTargetContributor(ProxyGenerationContext context, INamingScope namingScope, + Type targetType) + : base(context, namingScope) { this.targetType = targetType; } protected override IEnumerable GetCollectors() { - var targetItem = new ClassMembersCollector(targetType) { Logger = Logger }; + var targetItem = new ClassMembersCollector(Context, targetType); yield return targetItem; foreach (var @interface in interfaces) { - var item = new InterfaceMembersOnClassCollector(@interface, true, - targetType.GetInterfaceMap(@interface)) { Logger = Logger }; + var item = new InterfaceMembersOnClassCollector(Context, @interface, true, targetType.GetInterfaceMap(@interface)); yield return item; } } @@ -87,16 +87,12 @@ private Type BuildInvocationType(MetaMethod method, ClassEmitter @class) var methodInfo = method.Method; if (!method.HasTarget) { - return new InheritanceInvocationTypeGenerator(targetType, - method, - null, null) + return new InheritanceInvocationTypeGenerator(Context, targetType, method, null, null) .Generate(@class, namingScope) .BuildType(); } var callback = CreateCallbackMethod(@class, methodInfo, method.MethodOnTarget); - return new InheritanceInvocationTypeGenerator(callback.DeclaringType, - method, - callback, null) + return new InheritanceInvocationTypeGenerator(Context, callback.DeclaringType, method, callback, null) .Generate(@class, namingScope) .BuildType(); } @@ -132,7 +128,7 @@ private MethodGenerator ExplicitlyImplementedInterfaceMethodGenerator(MetaMethod { var @delegate = GetDelegateType(method, @class); var contributor = GetContributor(@delegate, method); - var invocation = new InheritanceInvocationTypeGenerator(targetType, method, null, contributor) + var invocation = new InheritanceInvocationTypeGenerator(Context, targetType, method, null, contributor) .Generate(@class, namingScope) .BuildType(); return new MethodWithInvocationGenerator(method, @@ -166,7 +162,7 @@ private Type GetDelegateType(MetaMethod method, ClassEmitter @class) null); return scope.TypeCache.GetOrAddWithoutTakingLock(key, _ => - new DelegateTypeGenerator(method, targetType) + new DelegateTypeGenerator(Context, method, targetType) .Generate(@class, namingScope) .BuildType()); } diff --git a/src/Castle.Core/DynamicProxy/Contributors/ClassProxyWithTargetTargetContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/ClassProxyWithTargetTargetContributor.cs index e9ab21fc32..ff9973f771 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/ClassProxyWithTargetTargetContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/ClassProxyWithTargetTargetContributor.cs @@ -29,21 +29,21 @@ internal class ClassProxyWithTargetTargetContributor : CompositeTypeContributor { private readonly Type targetType; - public ClassProxyWithTargetTargetContributor(Type targetType, INamingScope namingScope) - : base(namingScope) + public ClassProxyWithTargetTargetContributor(ProxyGenerationContext context, INamingScope namingScope, + Type targetType) + : base(context, namingScope) { this.targetType = targetType; } protected override IEnumerable GetCollectors() { - var targetItem = new WrappedClassMembersCollector(targetType) { Logger = Logger }; + var targetItem = new WrappedClassMembersCollector(Context, targetType); yield return targetItem; foreach (var @interface in interfaces) { - var item = new InterfaceMembersOnClassCollector(@interface, true, - targetType.GetInterfaceMap(@interface)) { Logger = Logger }; + var item = new InterfaceMembersOnClassCollector(Context, @interface, true, targetType.GetInterfaceMap(@interface)); yield return item; } } @@ -89,13 +89,12 @@ private Type BuildInvocationType(MetaMethod method, ClassEmitter @class) { if (!method.HasTarget) { - return new InheritanceInvocationTypeGenerator(targetType, - method, - null, null) + return new InheritanceInvocationTypeGenerator(Context, targetType, method, null, null) .Generate(@class, namingScope) .BuildType(); } - return new CompositionInvocationTypeGenerator(method.Method.DeclaringType, + return new CompositionInvocationTypeGenerator(Context, + method.Method.DeclaringType, method, method.Method, false, @@ -127,7 +126,7 @@ private Type GetDelegateType(MetaMethod method, ClassEmitter @class) null); return scope.TypeCache.GetOrAddWithoutTakingLock(key, _ => - new DelegateTypeGenerator(method, targetType) + new DelegateTypeGenerator(Context, method, targetType) .Generate(@class, namingScope) .BuildType()); } @@ -150,7 +149,7 @@ private MethodGenerator IndirectlyCalledMethodGenerator(MetaMethod method, Class { var @delegate = GetDelegateType(method, proxy); var contributor = GetContributor(@delegate, method); - var invocation = new CompositionInvocationTypeGenerator(targetType, method, null, false, contributor) + var invocation = new CompositionInvocationTypeGenerator(Context, targetType, method, null, false, contributor) .Generate(proxy, namingScope) .BuildType(); return new MethodWithInvocationGenerator(method, diff --git a/src/Castle.Core/DynamicProxy/Contributors/CompositeTypeContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/CompositeTypeContributor.cs index 90fd027a85..3ee37e924a 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/CompositeTypeContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/CompositeTypeContributor.cs @@ -26,36 +26,35 @@ namespace Castle.DynamicProxy.Contributors internal abstract class CompositeTypeContributor : ITypeContributor { + private readonly ProxyGenerationContext context; protected readonly INamingScope namingScope; protected readonly ICollection interfaces = new HashSet(); - private ILogger logger = NullLogger.Instance; private readonly List properties = new List(); private readonly List events = new List(); private readonly List methods = new List(); - protected CompositeTypeContributor(INamingScope namingScope) + protected CompositeTypeContributor(ProxyGenerationContext context, INamingScope namingScope) { + this.context = context; this.namingScope = namingScope; } - public ILogger Logger + protected ProxyGenerationContext Context { - get { return logger; } - set { logger = value; } + get { return context; } } - public void CollectElementsToProxy(IProxyGenerationHook hook, MetaType model) + public void CollectElementsToProxy(MetaType model) { - Debug.Assert(hook != null); Debug.Assert(model != null); var sink = new MembersCollectorSink(model, this); foreach (var collector in GetCollectors()) { - collector.CollectMembersToProxy(hook, sink); + collector.CollectMembersToProxy(sink); } } @@ -130,7 +129,7 @@ private void ImplementMethod(MetaMethod method, ClassEmitter @class, return; } var proxyMethod = generator.Generate(@class, namingScope); - foreach (var attribute in method.Method.GetNonInheritableAttributes()) + foreach (var attribute in method.Method.GetNonInheritableAttributes(Context)) { proxyMethod.DefineCustomAttribute(attribute.Builder); } diff --git a/src/Castle.Core/DynamicProxy/Contributors/DelegateTypeMembersCollector.cs b/src/Castle.Core/DynamicProxy/Contributors/DelegateTypeMembersCollector.cs index d3f7970164..eaaa25c279 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/DelegateTypeMembersCollector.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/DelegateTypeMembersCollector.cs @@ -22,12 +22,12 @@ namespace Castle.DynamicProxy.Contributors internal sealed class DelegateTypeMembersCollector : MembersCollector { - public DelegateTypeMembersCollector(Type delegateType) - : base(delegateType) + public DelegateTypeMembersCollector(ProxyGenerationContext context, Type delegateType) + : base(context, delegateType) { } - protected override MetaMethod GetMethodToGenerate(MethodInfo method, IProxyGenerationHook hook, bool isStandalone) + protected override MetaMethod GetMethodToGenerate(MethodInfo method, bool isStandalone) { if (method.Name == "Invoke" && method.DeclaringType.IsDelegateType()) { diff --git a/src/Castle.Core/DynamicProxy/Contributors/ITypeContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/ITypeContributor.cs index 64ab060dda..cf49a1ca86 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/ITypeContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/ITypeContributor.cs @@ -22,7 +22,7 @@ namespace Castle.DynamicProxy.Contributors /// internal interface ITypeContributor { - void CollectElementsToProxy(IProxyGenerationHook hook, MetaType model); + void CollectElementsToProxy(MetaType model); void Generate(ClassEmitter @class); } diff --git a/src/Castle.Core/DynamicProxy/Contributors/InterfaceMembersCollector.cs b/src/Castle.Core/DynamicProxy/Contributors/InterfaceMembersCollector.cs index bb0fdc81de..e099bb866e 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/InterfaceMembersCollector.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/InterfaceMembersCollector.cs @@ -21,19 +21,19 @@ namespace Castle.DynamicProxy.Contributors internal class InterfaceMembersCollector : MembersCollector { - public InterfaceMembersCollector(Type @interface) - : base(@interface) + public InterfaceMembersCollector(ProxyGenerationContext context, Type @interface) + : base(context, @interface) { } - protected override MetaMethod GetMethodToGenerate(MethodInfo method, IProxyGenerationHook hook, bool isStandalone) + protected override MetaMethod GetMethodToGenerate(MethodInfo method, bool isStandalone) { if (ProxyUtil.IsAccessibleMethod(method) == false) { return null; } - var proxyable = AcceptMethod(method, false, hook); + var proxyable = AcceptMethod(method, false); return new MetaMethod(method, method, isStandalone, proxyable, false); } } diff --git a/src/Castle.Core/DynamicProxy/Contributors/InterfaceMembersOnClassCollector.cs b/src/Castle.Core/DynamicProxy/Contributors/InterfaceMembersOnClassCollector.cs index 3e643cf802..8ebe0045e4 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/InterfaceMembersOnClassCollector.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/InterfaceMembersOnClassCollector.cs @@ -24,13 +24,15 @@ internal class InterfaceMembersOnClassCollector : MembersCollector private readonly InterfaceMapping map; private readonly bool onlyProxyVirtual; - public InterfaceMembersOnClassCollector(Type type, bool onlyProxyVirtual, InterfaceMapping map) : base(type) + public InterfaceMembersOnClassCollector(ProxyGenerationContext context, Type type, + bool onlyProxyVirtual, InterfaceMapping map) + : base(context, type) { this.onlyProxyVirtual = onlyProxyVirtual; this.map = map; } - protected override MetaMethod GetMethodToGenerate(MethodInfo method, IProxyGenerationHook hook, bool isStandalone) + protected override MetaMethod GetMethodToGenerate(MethodInfo method, bool isStandalone) { if (ProxyUtil.IsAccessibleMethod(method) == false) { @@ -44,7 +46,7 @@ protected override MetaMethod GetMethodToGenerate(MethodInfo method, IProxyGener var methodOnTarget = GetMethodOnTarget(method); - var proxyable = AcceptMethod(method, onlyProxyVirtual, hook); + var proxyable = AcceptMethod(method, onlyProxyVirtual); return new MetaMethod(method, methodOnTarget, isStandalone, proxyable, methodOnTarget.IsPrivate == false); } diff --git a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyTargetContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyTargetContributor.cs index deb0cde955..bb03ff0d2b 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyTargetContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyTargetContributor.cs @@ -27,8 +27,9 @@ internal class InterfaceProxyTargetContributor : CompositeTypeContributor private readonly bool canChangeTarget; private readonly Type proxyTargetType; - public InterfaceProxyTargetContributor(Type proxyTargetType, bool canChangeTarget, INamingScope namingScope) - : base(namingScope) + public InterfaceProxyTargetContributor(ProxyGenerationContext context, INamingScope namingScope, + Type proxyTargetType, bool canChangeTarget) + : base(context, namingScope) { this.proxyTargetType = proxyTargetType; this.canChangeTarget = canChangeTarget; @@ -39,15 +40,13 @@ protected override IEnumerable GetCollectors() foreach (var @interface in interfaces) { var item = GetCollectorForInterface(@interface); - item.Logger = Logger; yield return item; } } protected virtual MembersCollector GetCollectorForInterface(Type @interface) { - return new InterfaceMembersOnClassCollector(@interface, false, - proxyTargetType.GetInterfaceMap(@interface)); + return new InterfaceMembersOnClassCollector(Context, @interface, false, proxyTargetType.GetInterfaceMap(@interface)); } protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class, @@ -89,7 +88,8 @@ private Type GetInvocationType(MetaMethod method, ClassEmitter @class) // no locking required as we're already within a lock return scope.TypeCache.GetOrAddWithoutTakingLock(key, _ => - new CompositionInvocationTypeGenerator(method.Method.DeclaringType, + new CompositionInvocationTypeGenerator(Context, + method.Method.DeclaringType, method, method.Method, canChangeTarget, diff --git a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithOptionalTargetContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithOptionalTargetContributor.cs index 858a6fb205..18591768d0 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithOptionalTargetContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithOptionalTargetContributor.cs @@ -21,9 +21,10 @@ internal class InterfaceProxyWithOptionalTargetContributor : InterfaceProxyWitho { private readonly GetTargetReferenceDelegate getTargetReference; - public InterfaceProxyWithOptionalTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget, + public InterfaceProxyWithOptionalTargetContributor(ProxyGenerationContext context, INamingScope namingScope, + GetTargetExpressionDelegate getTarget, GetTargetReferenceDelegate getTargetReference) - : base(namingScope, getTarget) + : base(context, namingScope, getTarget) { this.getTargetReference = getTargetReference; canChangeTarget = true; diff --git a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithTargetInterfaceTargetContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithTargetInterfaceTargetContributor.cs index b1f4525965..e792e3e810 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithTargetInterfaceTargetContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithTargetInterfaceTargetContributor.cs @@ -20,15 +20,15 @@ namespace Castle.DynamicProxy.Contributors internal class InterfaceProxyWithTargetInterfaceTargetContributor : InterfaceProxyTargetContributor { - public InterfaceProxyWithTargetInterfaceTargetContributor(Type proxyTargetType, bool allowChangeTarget, - INamingScope namingScope) - : base(proxyTargetType, allowChangeTarget, namingScope) + public InterfaceProxyWithTargetInterfaceTargetContributor(ProxyGenerationContext context, INamingScope namingScope, + Type proxyTargetType, bool allowChangeTarget) + : base(context, namingScope, proxyTargetType, allowChangeTarget) { } protected override MembersCollector GetCollectorForInterface(Type @interface) { - return new InterfaceMembersCollector(@interface); + return new InterfaceMembersCollector(Context, @interface); } } } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs index 3910e426e3..4f0bf3be9d 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs @@ -27,8 +27,9 @@ internal class InterfaceProxyWithoutTargetContributor : CompositeTypeContributor private readonly GetTargetExpressionDelegate getTargetExpression; protected bool canChangeTarget = false; - public InterfaceProxyWithoutTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget) - : base(namingScope) + public InterfaceProxyWithoutTargetContributor(ProxyGenerationContext context, INamingScope namingScope, + GetTargetExpressionDelegate getTarget) + : base(context, namingScope) { getTargetExpression = getTarget; } @@ -37,7 +38,7 @@ protected override IEnumerable GetCollectors() { foreach (var @interface in interfaces) { - var item = new InterfaceMembersCollector(@interface); + var item = new InterfaceMembersCollector(Context, @interface); yield return item; } } @@ -85,7 +86,8 @@ private Type GetInvocationType(MetaMethod method, ClassEmitter emitter) // no locking required as we're already within a lock return scope.TypeCache.GetOrAddWithoutTakingLock(key, _ => - new CompositionInvocationTypeGenerator(methodInfo.DeclaringType, + new CompositionInvocationTypeGenerator(Context, + methodInfo.DeclaringType, method, methodInfo, canChangeTarget, diff --git a/src/Castle.Core/DynamicProxy/Contributors/MembersCollector.cs b/src/Castle.Core/DynamicProxy/Contributors/MembersCollector.cs index 487a8903f3..82bbd57eec 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/MembersCollector.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/MembersCollector.cs @@ -26,22 +26,22 @@ namespace Castle.DynamicProxy.Contributors internal abstract class MembersCollector { private const BindingFlags Flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; - private ILogger logger = NullLogger.Instance; + private readonly ProxyGenerationContext context; protected readonly Type type; - protected MembersCollector(Type type) + protected MembersCollector(ProxyGenerationContext context, Type type) { + this.context = context; this.type = type; } - public ILogger Logger + protected ProxyGenerationContext Context { - get { return logger; } - set { logger = value; } + get { return context; } } - public virtual void CollectMembersToProxy(IProxyGenerationHook hook, IMembersCollectorSink sink) + public virtual void CollectMembersToProxy(IMembersCollectorSink sink) { var checkedMethods = new HashSet(); @@ -101,7 +101,7 @@ void AddProperty(PropertyInfo property) return; } - var nonInheritableAttributes = property.GetNonInheritableAttributes(); + var nonInheritableAttributes = property.GetNonInheritableAttributes(Context); var arguments = property.GetIndexParameters(); sink.Add(new MetaProperty(property.Name, @@ -146,7 +146,7 @@ MetaMethod AddMethod(MethodInfo method, bool isStandalone) return null; } - var methodToGenerate = GetMethodToGenerate(method, hook, isStandalone); + var methodToGenerate = GetMethodToGenerate(method, isStandalone); if (methodToGenerate != null) { sink.Add(methodToGenerate); @@ -156,25 +156,25 @@ MetaMethod AddMethod(MethodInfo method, bool isStandalone) } } - protected abstract MetaMethod GetMethodToGenerate(MethodInfo method, IProxyGenerationHook hook, bool isStandalone); + protected abstract MetaMethod GetMethodToGenerate(MethodInfo method, bool isStandalone); /// /// Performs some basic screening and invokes the /// to select methods. /// - protected bool AcceptMethod(MethodInfo method, bool onlyVirtuals, IProxyGenerationHook hook) + protected bool AcceptMethod(MethodInfo method, bool onlyVirtuals) { - return AcceptMethodPreScreen(method, onlyVirtuals, hook) && hook.ShouldInterceptMethod(type, method); + return AcceptMethodPreScreen(method, onlyVirtuals) && Context.Hook.ShouldInterceptMethod(type, method); } /// /// Performs some basic screening to filter out non-interceptable methods. /// /// - /// The will get invoked for non-interceptable method notification only; + /// The will get invoked for non-interceptable method notification only; /// it does not get asked whether or not to intercept the . /// - protected bool AcceptMethodPreScreen(MethodInfo method, bool onlyVirtuals, IProxyGenerationHook hook) + protected bool AcceptMethodPreScreen(MethodInfo method, bool onlyVirtuals) { if (IsInternalAndNotVisibleToDynamicProxy(method)) { @@ -188,9 +188,9 @@ protected bool AcceptMethodPreScreen(MethodInfo method, bool onlyVirtuals, IProx method.IsGetType() == false && method.IsMemberwiseClone() == false) { - Logger.DebugFormat("Excluded non-overridable method {0} on {1} because it cannot be intercepted.", method.Name, - method.DeclaringType.FullName); - hook.NonProxyableMemberNotification(type, method); + Context.Logger.DebugFormat("Excluded non-overridable method {0} on {1} because it cannot be intercepted.", method.Name, + method.DeclaringType.FullName); + Context.Hook.NonProxyableMemberNotification(type, method); } return false; } @@ -198,8 +198,8 @@ protected bool AcceptMethodPreScreen(MethodInfo method, bool onlyVirtuals, IProx // we can never intercept a sealed (final) method if (method.IsFinal) { - Logger.DebugFormat("Excluded sealed method {0} on {1} because it cannot be intercepted.", method.Name, - method.DeclaringType.FullName); + Context.Logger.DebugFormat("Excluded sealed method {0} on {1} because it cannot be intercepted.", method.Name, + method.DeclaringType.FullName); return false; } diff --git a/src/Castle.Core/DynamicProxy/Contributors/MixinContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/MixinContributor.cs index e6070994ef..649faa1290 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/MixinContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/MixinContributor.cs @@ -31,8 +31,9 @@ internal class MixinContributor : CompositeTypeContributor private readonly IDictionary fields = new SortedDictionary(new FieldReferenceComparer()); private readonly GetTargetExpressionDelegate getTargetExpression; - public MixinContributor(INamingScope namingScope, bool canChangeTarget) - : base(namingScope) + public MixinContributor(ProxyGenerationContext context, INamingScope namingScope, + bool canChangeTarget) + : base(context, namingScope) { this.canChangeTarget = canChangeTarget; getTargetExpression = BuildGetTargetExpression(); @@ -76,12 +77,12 @@ protected override IEnumerable GetCollectors() MembersCollector item; if (@interface.IsInterface) { - item = new InterfaceMembersCollector(@interface); + item = new InterfaceMembersCollector(Context, @interface); } else { Debug.Assert(@interface.IsDelegateType()); - item = new DelegateTypeMembersCollector(@interface); + item = new DelegateTypeMembersCollector(Context, @interface); } yield return item; } @@ -141,7 +142,8 @@ private Type GetInvocationType(MetaMethod method, ClassEmitter emitter) // no locking required as we're already within a lock return scope.TypeCache.GetOrAddWithoutTakingLock(key, _ => - new CompositionInvocationTypeGenerator(method.Method.DeclaringType, + new CompositionInvocationTypeGenerator(Context, + method.Method.DeclaringType, method, method.Method, canChangeTarget, diff --git a/src/Castle.Core/DynamicProxy/Contributors/NonInheritableAttributesContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/NonInheritableAttributesContributor.cs index 0f30bec9af..ae6e92ddb6 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/NonInheritableAttributesContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/NonInheritableAttributesContributor.cs @@ -25,22 +25,24 @@ namespace Castle.DynamicProxy.Contributors /// internal sealed class NonInheritableAttributesContributor : ITypeContributor { + private readonly ProxyGenerationContext context; private readonly Type targetType; - public NonInheritableAttributesContributor(Type targetType) + public NonInheritableAttributesContributor(ProxyGenerationContext context, Type targetType) { + this.context = context; this.targetType = targetType; } public void Generate(ClassEmitter emitter) { - foreach (var attribute in targetType.GetNonInheritableAttributes()) + foreach (var attribute in targetType.GetNonInheritableAttributes(context)) { emitter.DefineCustomAttribute(attribute.Builder); } } - public void CollectElementsToProxy(IProxyGenerationHook hook, MetaType model) + public void CollectElementsToProxy(MetaType model) { } } diff --git a/src/Castle.Core/DynamicProxy/Contributors/ProxyTargetAccessorContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/ProxyTargetAccessorContributor.cs index 32cdec1492..8d92f9014a 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/ProxyTargetAccessorContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/ProxyTargetAccessorContributor.cs @@ -34,7 +34,7 @@ public ProxyTargetAccessorContributor(Func getTargetReference, Type t this.targetType = targetType; } - public void CollectElementsToProxy(IProxyGenerationHook hook, MetaType model) + public void CollectElementsToProxy(MetaType model) { } diff --git a/src/Castle.Core/DynamicProxy/Contributors/SerializableContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/SerializableContributor.cs index fc6be52924..08927db442 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/SerializableContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/SerializableContributor.cs @@ -144,7 +144,7 @@ protected virtual void AddAddValueInvocation(ArgumentReference serializationInfo protected abstract void CustomizeGetObjectData(CodeBuilder builder, ArgumentReference serializationInfo, ArgumentReference streamingContext, ClassEmitter emitter); - public virtual void CollectElementsToProxy(IProxyGenerationHook hook, MetaType model) + public virtual void CollectElementsToProxy(MetaType model) { } } diff --git a/src/Castle.Core/DynamicProxy/Contributors/WrappedClassMembersCollector.cs b/src/Castle.Core/DynamicProxy/Contributors/WrappedClassMembersCollector.cs index eca221461b..c79f8970cc 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/WrappedClassMembersCollector.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/WrappedClassMembersCollector.cs @@ -24,32 +24,33 @@ namespace Castle.DynamicProxy.Contributors internal class WrappedClassMembersCollector : ClassMembersCollector { - public WrappedClassMembersCollector(Type type) : base(type) + public WrappedClassMembersCollector(ProxyGenerationContext context, Type type) + : base(context, type) { } - public override void CollectMembersToProxy(IProxyGenerationHook hook, IMembersCollectorSink sink) + public override void CollectMembersToProxy(IMembersCollectorSink sink) { - base.CollectMembersToProxy(hook, sink); - CollectFields(hook); + base.CollectMembersToProxy(sink); + CollectFields(); // TODO: perhaps we should also look for nested classes... } - protected override MetaMethod GetMethodToGenerate(MethodInfo method, IProxyGenerationHook hook, bool isStandalone) + protected override MetaMethod GetMethodToGenerate(MethodInfo method, bool isStandalone) { if (ProxyUtil.IsAccessibleMethod(method) == false) { return null; } - var interceptable = AcceptMethodPreScreen(method, true, hook); + var interceptable = AcceptMethodPreScreen(method, true); if (!interceptable) { //we don't need to do anything... return null; } - var accepted = hook.ShouldInterceptMethod(type, method); + var accepted = Context.Hook.ShouldInterceptMethod(type, method); return new MetaMethod(method, method, isStandalone, accepted, hasTarget: true); } @@ -65,7 +66,7 @@ protected virtual bool IsOKToBeOnProxy(FieldInfo field) return IsGeneratedByTheCompiler(field); } - private void CollectFields(IProxyGenerationHook hook) + private void CollectFields() { var fields = type.GetAllFields(); foreach (var field in fields) @@ -75,7 +76,7 @@ private void CollectFields(IProxyGenerationHook hook) continue; } - hook.NonProxyableMemberNotification(type, field); + Context.Hook.NonProxyableMemberNotification(type, field); } } } diff --git a/src/Castle.Core/DynamicProxy/DefaultProxyBuilder.cs b/src/Castle.Core/DynamicProxy/DefaultProxyBuilder.cs index c8454aa795..8d1c665918 100644 --- a/src/Castle.Core/DynamicProxy/DefaultProxyBuilder.cs +++ b/src/Castle.Core/DynamicProxy/DefaultProxyBuilder.cs @@ -65,7 +65,9 @@ public Type CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesT AssertValidTypes(additionalInterfacesToProxy, nameof(additionalInterfacesToProxy)); AssertValidMixins(options, nameof(options)); - var generator = new ClassProxyGenerator(scope, classToProxy, additionalInterfacesToProxy, options) { Logger = logger }; + var context = new ProxyGenerationContext(options, Logger); + + var generator = new ClassProxyGenerator(context, scope, classToProxy, additionalInterfacesToProxy); return generator.GetProxyType(); } @@ -76,8 +78,9 @@ public Type CreateClassProxyTypeWithTarget(Type classToProxy, Type[] additionalI AssertValidTypes(additionalInterfacesToProxy, nameof(additionalInterfacesToProxy)); AssertValidMixins(options, nameof(options)); - var generator = new ClassProxyWithTargetGenerator(scope, classToProxy, additionalInterfacesToProxy, options) - { Logger = logger }; + var context = new ProxyGenerationContext(options, Logger); + + var generator = new ClassProxyWithTargetGenerator(context, scope, classToProxy, additionalInterfacesToProxy); return generator.GetProxyType(); } @@ -89,7 +92,9 @@ public Type CreateInterfaceProxyTypeWithTarget(Type interfaceToProxy, Type[] add AssertValidTypes(additionalInterfacesToProxy, nameof(additionalInterfacesToProxy)); AssertValidMixins(options, nameof(options)); - var generator = new InterfaceProxyWithTargetGenerator(scope, interfaceToProxy, additionalInterfacesToProxy, targetType, options) { Logger = logger }; + var context = new ProxyGenerationContext(options, Logger); + + var generator = new InterfaceProxyWithTargetGenerator(context, scope, interfaceToProxy, additionalInterfacesToProxy, targetType); return generator.GetProxyType(); } @@ -100,7 +105,9 @@ public Type CreateInterfaceProxyTypeWithTargetInterface(Type interfaceToProxy, T AssertValidTypes(additionalInterfacesToProxy, nameof(additionalInterfacesToProxy)); AssertValidMixins(options, nameof(options)); - var generator = new InterfaceProxyWithTargetInterfaceGenerator(scope, interfaceToProxy, additionalInterfacesToProxy, interfaceToProxy, options) { Logger = logger }; + var context = new ProxyGenerationContext(options, Logger); + + var generator = new InterfaceProxyWithTargetInterfaceGenerator(context, scope, interfaceToProxy, additionalInterfacesToProxy, interfaceToProxy); return generator.GetProxyType(); } @@ -111,7 +118,9 @@ public Type CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] AssertValidTypes(additionalInterfacesToProxy, nameof(additionalInterfacesToProxy)); AssertValidMixins(options, nameof(options)); - var generator = new InterfaceProxyWithoutTargetGenerator(scope, interfaceToProxy, additionalInterfacesToProxy, typeof(object), options) { Logger = logger }; + var context = new ProxyGenerationContext(options, Logger); + + var generator = new InterfaceProxyWithoutTargetGenerator(context, scope, interfaceToProxy, additionalInterfacesToProxy, typeof(object)); return generator.GetProxyType(); } diff --git a/src/Castle.Core/DynamicProxy/Generators/AttributesToAvoidReplicating.cs b/src/Castle.Core/DynamicProxy/Generators/AttributesToAvoidReplicating.cs deleted file mode 100644 index e045a50bdf..0000000000 --- a/src/Castle.Core/DynamicProxy/Generators/AttributesToAvoidReplicating.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace Castle.DynamicProxy.Generators -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Reflection; - - public static class AttributesToAvoidReplicating - { - private static readonly object lockObject = new object(); - - private static IList attributes; - - static AttributesToAvoidReplicating() - { - attributes = new List() - { - typeof(System.Runtime.InteropServices.ComImportAttribute), - typeof(System.Runtime.InteropServices.MarshalAsAttribute), - typeof(System.Runtime.InteropServices.TypeIdentifierAttribute), - typeof(System.Security.Permissions.SecurityAttribute), - }; - } - - public static void Add(Type attribute) - { - // note: this class is made thread-safe by replacing the backing list rather than adding to it - lock (lockObject) - { - attributes = new List(attributes) { attribute }; - } - } - - public static void Add() - { - Add(typeof(T)); - } - - public static bool Contains(Type attribute) - { - return attributes.Contains(attribute); - } - - internal static bool ShouldAvoid(Type attribute) - { - return attributes.Any(attr => attr.IsAssignableFrom(attribute)); - } - } -} \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/BaseClassProxyGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/BaseClassProxyGenerator.cs index 02f6012380..b2b6db572d 100644 --- a/src/Castle.Core/DynamicProxy/Generators/BaseClassProxyGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/BaseClassProxyGenerator.cs @@ -25,8 +25,9 @@ namespace Castle.DynamicProxy.Generators internal abstract class BaseClassProxyGenerator : BaseProxyGenerator { - protected BaseClassProxyGenerator(ModuleScope scope, Type targetType, Type[] interfaces, ProxyGenerationOptions options) - : base(scope, targetType, interfaces, options) + protected BaseClassProxyGenerator(ProxyGenerationContext context, ModuleScope scope, + Type targetType, Type[] interfaces) + : base(context, scope, targetType, interfaces) { EnsureDoesNotImplementIProxyTargetAccessor(targetType, nameof(targetType)); } @@ -50,9 +51,9 @@ protected sealed override Type GenerateType(string name, INamingScope namingScop // Collect methods foreach (var contributor in contributors) { - contributor.CollectElementsToProxy(ProxyGenerationOptions.Hook, model); + contributor.CollectElementsToProxy(model); } - ProxyGenerationOptions.Hook.MethodsInspected(); + Context.Hook.MethodsInspected(); var emitter = BuildClassEmitter(name, targetType, allInterfaces); @@ -96,7 +97,7 @@ protected sealed override Type GenerateType(string name, INamingScope namingScop CompleteInitCacheMethod(cctor.CodeBuilder); // non-inheritable attributes from proxied type - var nonInheritableAttributesContributor = new NonInheritableAttributesContributor(targetType); + var nonInheritableAttributesContributor = new NonInheritableAttributesContributor(Context, targetType); nonInheritableAttributesContributor.Generate(emitter); // Crosses fingers and build type @@ -122,7 +123,7 @@ private IEnumerable GetTypeImplementerMapping(out IEnumerable GetTypeImplementerMapping(out IEnumerable 0) { - var additionalInterfacesContributor = new InterfaceProxyWithoutTargetContributor(namingScope, (c, m) => NullExpression.Instance) { Logger = Logger }; + var additionalInterfacesContributor = new InterfaceProxyWithoutTargetContributor(Context, namingScope, (c, m) => NullExpression.Instance); contributorsList.Add(additionalInterfacesContributor); foreach (var @interface in interfaces) diff --git a/src/Castle.Core/DynamicProxy/Generators/BaseInterfaceProxyGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/BaseInterfaceProxyGenerator.cs index 84e6b1186b..f437e01fbc 100644 --- a/src/Castle.Core/DynamicProxy/Generators/BaseInterfaceProxyGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/BaseInterfaceProxyGenerator.cs @@ -33,9 +33,9 @@ internal abstract class BaseInterfaceProxyGenerator : BaseProxyGenerator protected FieldReference targetField; - protected BaseInterfaceProxyGenerator(ModuleScope scope, Type targetType, Type[] interfaces, - Type proxyTargetType, ProxyGenerationOptions options) - : base(scope, targetType, interfaces, options) + protected BaseInterfaceProxyGenerator(ProxyGenerationContext context, ModuleScope scope, + Type targetType, Type[] interfaces, Type proxyTargetType) + : base(context, scope, targetType, interfaces) { CheckNotGenericTypeDefinition(proxyTargetType, nameof(proxyTargetType)); EnsureValidBaseType(ProxyGenerationOptions.BaseTypeForInterfaceProxy); @@ -93,10 +93,10 @@ protected override Type GenerateType(string typeName, INamingScope namingScope) // Collect methods foreach (var contributor in contributors) { - contributor.CollectElementsToProxy(ProxyGenerationOptions.Hook, model); + contributor.CollectElementsToProxy(model); } - ProxyGenerationOptions.Hook.MethodsInspected(); + Context.Hook.MethodsInspected(); ClassEmitter emitter; FieldReference interceptorsField; @@ -132,7 +132,7 @@ protected override Type GenerateType(string typeName, INamingScope namingScope) CompleteInitCacheMethod(cctor.CodeBuilder); // non-inheritable attributes from proxied type - var nonInheritableAttributesContributor = new NonInheritableAttributesContributor(targetType); + var nonInheritableAttributesContributor = new NonInheritableAttributesContributor(Context, targetType); nonInheritableAttributesContributor.Generate(emitter); // Crosses fingers and build type @@ -145,7 +145,7 @@ protected override Type GenerateType(string typeName, INamingScope namingScope) protected virtual InterfaceProxyWithoutTargetContributor GetContributorForAdditionalInterfaces( INamingScope namingScope) { - return new InterfaceProxyWithoutTargetContributor(namingScope, (c, m) => NullExpression.Instance) { Logger = Logger }; + return new InterfaceProxyWithoutTargetContributor(Context, namingScope, (c, m) => NullExpression.Instance); } protected virtual IEnumerable GetTypeImplementerMapping(Type proxyTargetType, @@ -164,7 +164,7 @@ protected virtual IEnumerable GetTypeImplementerMapping(Type proxyTargetTy // 2. then mixins if (ProxyGenerationOptions.HasMixins) { - var mixinContributor = new MixinContributor(namingScope, AllowChangeTarget) { Logger = Logger }; + var mixinContributor = new MixinContributor(Context, namingScope, AllowChangeTarget); contributorsList.Add(mixinContributor); foreach (var mixinInterface in ProxyGenerationOptions.MixinData.MixinInterfaces) diff --git a/src/Castle.Core/DynamicProxy/Generators/BaseProxyGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/BaseProxyGenerator.cs index 2d790409d6..d82aee5d35 100644 --- a/src/Castle.Core/DynamicProxy/Generators/BaseProxyGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/BaseProxyGenerator.cs @@ -38,31 +38,29 @@ internal abstract class BaseProxyGenerator { protected readonly Type targetType; protected readonly Type[] interfaces; + private readonly ProxyGenerationContext context; private readonly ModuleScope scope; - private ILogger logger = NullLogger.Instance; - private ProxyGenerationOptions proxyGenerationOptions; - protected BaseProxyGenerator(ModuleScope scope, Type targetType, Type[] interfaces, ProxyGenerationOptions proxyGenerationOptions) + protected BaseProxyGenerator(ProxyGenerationContext context, ModuleScope scope, + Type targetType, Type[] interfaces) { CheckNotGenericTypeDefinition(targetType, nameof(targetType)); CheckNotGenericTypeDefinitions(interfaces, nameof(interfaces)); + this.context = context; this.scope = scope; this.targetType = targetType; this.interfaces = TypeUtil.GetAllInterfaces(interfaces); - this.proxyGenerationOptions = proxyGenerationOptions; - this.proxyGenerationOptions.Initialize(); } - public ILogger Logger + protected ProxyGenerationContext Context { - get { return logger; } - set { logger = value; } + get { return context; } } protected ProxyGenerationOptions ProxyGenerationOptions { - get { return proxyGenerationOptions; } + get { return context.Options; } } protected ModuleScope Scope @@ -77,7 +75,7 @@ public Type GetProxyType() var proxyType = Scope.TypeCache.GetOrAdd(GetCacheKey(), cacheKey => { notFoundInTypeCache = true; - Logger.DebugFormat("No cached proxy type was found for target type {0}.", targetType.FullName); + Context.Logger.DebugFormat("No cached proxy type was found for target type {0}.", targetType.FullName); EnsureOptionsOverrideEqualsAndGetHashCode(); @@ -87,7 +85,7 @@ public Type GetProxyType() if (!notFoundInTypeCache) { - Logger.DebugFormat("Found cached proxy type {0} for target type {1}.", proxyType.FullName, targetType.FullName); + Context.Logger.DebugFormat("Found cached proxy type {0} for target type {1}.", proxyType.FullName, targetType.FullName); } return proxyType; @@ -131,7 +129,7 @@ protected virtual ClassEmitter BuildClassEmitter(string typeName, Type parentTyp CheckNotGenericTypeDefinition(parentType, nameof(parentType)); CheckNotGenericTypeDefinitions(interfaces, nameof(interfaces)); - return new ClassEmitter(Scope, typeName, parentType, interfaces); + return new ClassEmitter(Context, Scope, typeName, parentType, interfaces); } protected void CheckNotGenericTypeDefinition(Type type, string argumentName) @@ -200,14 +198,14 @@ protected virtual void CreateTypeAttributes(ClassEmitter emitter) protected void EnsureOptionsOverrideEqualsAndGetHashCode() { - if (Logger.IsWarnEnabled) + if (Context.Logger.IsWarnEnabled) { // Check the proxy generation hook - if (!OverridesEqualsAndGetHashCode(ProxyGenerationOptions.Hook.GetType())) + if (!OverridesEqualsAndGetHashCode(Context.Hook.GetType())) { - Logger.WarnFormat("The IProxyGenerationHook type {0} does not override both Equals and GetHashCode. " + - "If these are not correctly overridden caching will fail to work causing performance problems.", - ProxyGenerationOptions.Hook.GetType().FullName); + Context.Logger.WarnFormat("The IProxyGenerationHook type {0} does not override both Equals and GetHashCode. " + + "If these are not correctly overridden caching will fail to work causing performance problems.", + Context.Hook.GetType().FullName); } // Interceptor selectors no longer need to override Equals and GetHashCode @@ -253,7 +251,7 @@ protected void GenerateConstructor(ClassEmitter emitter, ConstructorInfo baseCon for (int i = 0, n = baseConstructorParams.Length; i < n; ++i) { var parameterBuilder = constructor.ConstructorBuilder.DefineParameter(offset + i, baseConstructorParams[i].Attributes, baseConstructorParams[i].Name); - foreach (var attribute in baseConstructorParams[i].GetNonInheritableAttributes()) + foreach (var attribute in baseConstructorParams[i].GetNonInheritableAttributes(Context)) { parameterBuilder.SetCustomAttribute(attribute.Builder); } diff --git a/src/Castle.Core/DynamicProxy/Generators/ClassProxyGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/ClassProxyGenerator.cs index 7d713f15dc..a502bde7fb 100644 --- a/src/Castle.Core/DynamicProxy/Generators/ClassProxyGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/ClassProxyGenerator.cs @@ -24,8 +24,9 @@ namespace Castle.DynamicProxy.Generators internal sealed class ClassProxyGenerator : BaseClassProxyGenerator { - public ClassProxyGenerator(ModuleScope scope, Type targetType, Type[] interfaces, ProxyGenerationOptions options) - : base(scope, targetType, interfaces, options) + public ClassProxyGenerator(ProxyGenerationContext context, ModuleScope scope, + Type targetType, Type[] interfaces) + : base(context, scope, targetType, interfaces) { } @@ -45,7 +46,7 @@ protected override SerializableContributor GetSerializableContributor() protected override CompositeTypeContributor GetProxyTargetContributor(INamingScope namingScope) { - return new ClassProxyTargetContributor(targetType, namingScope) { Logger = Logger }; + return new ClassProxyTargetContributor(Context, namingScope, targetType); } protected override ProxyTargetAccessorContributor GetProxyTargetAccessorContributor() diff --git a/src/Castle.Core/DynamicProxy/Generators/ClassProxyWithTargetGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/ClassProxyWithTargetGenerator.cs index c7f6fe6ad5..4acd58f737 100644 --- a/src/Castle.Core/DynamicProxy/Generators/ClassProxyWithTargetGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/ClassProxyWithTargetGenerator.cs @@ -31,9 +31,9 @@ internal sealed class ClassProxyWithTargetGenerator : BaseClassProxyGenerator { private FieldReference targetField; - public ClassProxyWithTargetGenerator(ModuleScope scope, Type targetType, Type[] interfaces, - ProxyGenerationOptions options) - : base(scope, targetType, interfaces, options) + public ClassProxyWithTargetGenerator(ProxyGenerationContext context, ModuleScope scope, + Type targetType, Type[] interfaces) + : base(context, scope, targetType, interfaces) { } @@ -59,7 +59,7 @@ protected override SerializableContributor GetSerializableContributor() protected override CompositeTypeContributor GetProxyTargetContributor(INamingScope namingScope) { - return new ClassProxyWithTargetTargetContributor(targetType, namingScope) { Logger = Logger }; + return new ClassProxyWithTargetTargetContributor(Context, namingScope, targetType); } protected override ProxyTargetAccessorContributor GetProxyTargetAccessorContributor() diff --git a/src/Castle.Core/DynamicProxy/Generators/CompositionInvocationTypeGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/CompositionInvocationTypeGenerator.cs index 7222725f31..5ff64fbc0e 100644 --- a/src/Castle.Core/DynamicProxy/Generators/CompositionInvocationTypeGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/CompositionInvocationTypeGenerator.cs @@ -27,9 +27,9 @@ internal class CompositionInvocationTypeGenerator : InvocationTypeGenerator { public static readonly Type BaseType = typeof(CompositionInvocation); - public CompositionInvocationTypeGenerator(Type target, MetaMethod method, MethodInfo callback, bool canChangeTarget, + public CompositionInvocationTypeGenerator(ProxyGenerationContext context, Type target, MetaMethod method, MethodInfo callback, bool canChangeTarget, IInvocationCreationContributor contributor) - : base(target, method, callback, canChangeTarget, contributor) + : base(context, target, method, callback, canChangeTarget, contributor) { } diff --git a/src/Castle.Core/DynamicProxy/Generators/DelegateTypeGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/DelegateTypeGenerator.cs index 8efd6d40cf..d93cb5efab 100644 --- a/src/Castle.Core/DynamicProxy/Generators/DelegateTypeGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/DelegateTypeGenerator.cs @@ -29,11 +29,13 @@ internal class DelegateTypeGenerator : IGenerator TypeAttributes.AnsiClass | TypeAttributes.AutoClass; + private readonly ProxyGenerationContext context; private readonly MetaMethod method; private readonly Type targetType; - public DelegateTypeGenerator(MetaMethod method, Type targetType) + public DelegateTypeGenerator(ProxyGenerationContext context, MetaMethod method, Type targetType) { + this.context = context; this.method = method; this.targetType = targetType; } @@ -74,7 +76,8 @@ private AbstractTypeEmitter GetEmitter(ClassEmitter @class, INamingScope namingS method.Method.Name); var uniqueName = namingScope.ParentScope.GetUniqueName(suggestedName); - var @delegate = new ClassEmitter(@class.ModuleScope, + var @delegate = new ClassEmitter(context, + @class.ModuleScope, uniqueName, typeof(MulticastDelegate), Type.EmptyTypes, diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs index d2f41e39c2..0bf83a36db 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs @@ -36,6 +36,7 @@ internal abstract class AbstractTypeEmitter private readonly List methods; + private readonly ProxyGenerationContext context; private readonly Dictionary name2GenericType; private readonly List nested; private readonly List properties; @@ -43,8 +44,9 @@ internal abstract class AbstractTypeEmitter private GenericTypeParameterBuilder[] genericTypeParams; - protected AbstractTypeEmitter(TypeBuilder typeBuilder) + protected AbstractTypeEmitter(ProxyGenerationContext context, TypeBuilder typeBuilder) { + this.context = context; typebuilder = typeBuilder; nested = new List(); methods = new List(); @@ -78,6 +80,11 @@ public TypeBuilder TypeBuilder get { return typebuilder; } } + protected ProxyGenerationContext Context + { + get { return context; } + } + public void AddCustomAttributes(IEnumerable additionalAttributes) { foreach (var attribute in additionalAttributes) @@ -113,7 +120,7 @@ public void CopyGenericParametersFromMethod(MethodInfo methodToCopyGenericsFrom) throw new InvalidOperationException("Cannot invoke me twice"); } - SetGenericTypeParameters(GenericUtil.CopyGenericArguments(methodToCopyGenericsFrom, typebuilder, name2GenericType)); + SetGenericTypeParameters(GenericUtil.CopyGenericArguments(methodToCopyGenericsFrom, typebuilder, Context, name2GenericType)); } public ConstructorEmitter CreateConstructor(params ArgumentReference[] arguments) @@ -140,7 +147,7 @@ public void CreateDefaultConstructor() public EventEmitter CreateEvent(string name, EventAttributes atts, Type type) { - var eventEmitter = new EventEmitter(this, name, atts, type); + var eventEmitter = new EventEmitter(Context, this, name, atts, type); events.Add(eventEmitter); return eventEmitter; } @@ -172,7 +179,7 @@ public FieldReference CreateField(string name, Type fieldType, FieldAttributes a public MethodEmitter CreateMethod(string name, MethodAttributes attrs, Type returnType, params Type[] argumentTypes) { - var member = new MethodEmitter(this, name, attrs, returnType, argumentTypes ?? Type.EmptyTypes); + var member = new MethodEmitter(Context, this, name, attrs, returnType, argumentTypes ?? Type.EmptyTypes); methods.Add(member); return member; } @@ -189,14 +196,14 @@ public MethodEmitter CreateMethod(string name, MethodInfo methodToUseAsATemplate public MethodEmitter CreateMethod(string name, MethodAttributes attributes, MethodInfo methodToUseAsATemplate) { - var method = new MethodEmitter(this, name, attributes, methodToUseAsATemplate); + var method = new MethodEmitter(Context, this, name, attributes, methodToUseAsATemplate); methods.Add(method); return method; } public PropertyEmitter CreateProperty(string name, PropertyAttributes attributes, Type propertyType, Type[] arguments) { - var propEmitter = new PropertyEmitter(this, name, attributes, propertyType, arguments); + var propEmitter = new PropertyEmitter(Context, this, name, attributes, propertyType, arguments); properties.Add(propEmitter); return propEmitter; } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs index cb2023bc87..f32924682b 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs @@ -29,15 +29,15 @@ internal class ClassEmitter : AbstractTypeEmitter private readonly ModuleScope moduleScope; - public ClassEmitter(ModuleScope modulescope, string name, Type baseType, IEnumerable interfaces) - : this(modulescope, name, baseType, interfaces, DefaultAttributes, forceUnsigned: false) + public ClassEmitter(ProxyGenerationContext context, ModuleScope modulescope, string name, Type baseType, IEnumerable interfaces) + : this(context, modulescope, name, baseType, interfaces, DefaultAttributes, forceUnsigned: false) { } - public ClassEmitter(ModuleScope modulescope, string name, Type baseType, IEnumerable interfaces, + public ClassEmitter(ProxyGenerationContext context, ModuleScope modulescope, string name, Type baseType, IEnumerable interfaces, TypeAttributes flags, bool forceUnsigned) - : this(CreateTypeBuilder(modulescope, name, baseType, interfaces, flags, forceUnsigned)) + : this(context, CreateTypeBuilder(modulescope, name, baseType, interfaces, flags, forceUnsigned)) { interfaces = InitializeGenericArgumentsFromBases(ref baseType, interfaces); @@ -60,8 +60,8 @@ public ClassEmitter(ModuleScope modulescope, string name, Type baseType, IEnumer moduleScope = modulescope; } - public ClassEmitter(TypeBuilder typeBuilder) - : base(typeBuilder) + public ClassEmitter(ProxyGenerationContext context, TypeBuilder typeBuilder) + : base(context, typeBuilder) { } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs index 08ad72ea3e..a99ed332b8 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs @@ -20,13 +20,14 @@ namespace Castle.DynamicProxy.Generators.Emitters internal class EventEmitter : IMemberEmitter { + private readonly ProxyGenerationContext context; private readonly EventBuilder eventBuilder; private readonly Type type; private readonly AbstractTypeEmitter typeEmitter; private MethodEmitter addMethod; private MethodEmitter removeMethod; - public EventEmitter(AbstractTypeEmitter typeEmitter, string name, EventAttributes attributes, Type type) + public EventEmitter(ProxyGenerationContext context, AbstractTypeEmitter typeEmitter, string name, EventAttributes attributes, Type type) { if (name == null) { @@ -36,6 +37,7 @@ public EventEmitter(AbstractTypeEmitter typeEmitter, string name, EventAttribute { throw new ArgumentNullException(nameof(type)); } + this.context = context; this.typeEmitter = typeEmitter; this.type = type; eventBuilder = typeEmitter.TypeBuilder.DefineEvent(name, attributes, type); @@ -58,7 +60,7 @@ public MethodEmitter CreateAddMethod(string addMethodName, MethodAttributes attr throw new InvalidOperationException("An add method exists"); } - addMethod = new MethodEmitter(typeEmitter, addMethodName, attributes, methodToOverride); + addMethod = new MethodEmitter(context, typeEmitter, addMethodName, attributes, methodToOverride); return addMethod; } @@ -69,7 +71,7 @@ public MethodEmitter CreateRemoveMethod(string removeMethodName, MethodAttribute { throw new InvalidOperationException("A remove method exists"); } - removeMethod = new MethodEmitter(typeEmitter, removeMethodName, attributes, methodToOverride); + removeMethod = new MethodEmitter(context, typeEmitter, removeMethodName, attributes, methodToOverride); return removeMethod; } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs index 0447dc7533..efb79c4acc 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs @@ -30,21 +30,23 @@ internal class GenericUtil public static GenericTypeParameterBuilder[] CopyGenericArguments( MethodInfo methodToCopyGenericsFrom, TypeBuilder builder, + ProxyGenerationContext context, Dictionary name2GenericType) { return CopyGenericArguments(methodToCopyGenericsFrom, name2GenericType, - builder.DefineGenericParameters); + builder.DefineGenericParameters, context); } public static GenericTypeParameterBuilder[] CopyGenericArguments( MethodInfo methodToCopyGenericsFrom, MethodBuilder builder, + ProxyGenerationContext context, Dictionary name2GenericType) { return CopyGenericArguments(methodToCopyGenericsFrom, name2GenericType, - builder.DefineGenericParameters); + builder.DefineGenericParameters, context); } public static Type ExtractCorrectType(Type paramType, Dictionary name2GenericType) @@ -185,7 +187,8 @@ private static Type[] AdjustGenericConstraints(MethodInfo methodToCopyGenericsFr private static GenericTypeParameterBuilder[] CopyGenericArguments( MethodInfo methodToCopyGenericsFrom, Dictionary name2GenericType, - ApplyGenArgs genericParameterGenerator) + ApplyGenArgs genericParameterGenerator, + ProxyGenerationContext context) { var originalGenericArguments = methodToCopyGenericsFrom.GetGenericArguments(); if (originalGenericArguments.Length == 0) @@ -205,7 +208,7 @@ private static GenericTypeParameterBuilder[] CopyGenericArguments( var constraints = AdjustGenericConstraints(methodToCopyGenericsFrom, newGenericParameters, originalGenericArguments, originalGenericArguments[i].GetGenericParameterConstraints()); newGenericParameters[i].SetInterfaceConstraints(constraints); - CopyNonInheritableAttributes(newGenericParameters[i], originalGenericArguments[i]); + CopyNonInheritableAttributes(newGenericParameters[i], originalGenericArguments[i], context); } catch (NotSupportedException) { @@ -221,9 +224,10 @@ private static GenericTypeParameterBuilder[] CopyGenericArguments( } private static void CopyNonInheritableAttributes(GenericTypeParameterBuilder newGenericParameter, - Type originalGenericArgument) + Type originalGenericArgument, + ProxyGenerationContext context) { - foreach (var attribute in originalGenericArgument.GetNonInheritableAttributes()) + foreach (var attribute in originalGenericArgument.GetNonInheritableAttributes(context)) { newGenericParameter.SetCustomAttribute(attribute.Builder); } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs index b508e96f35..ac4a17c1a8 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs @@ -27,35 +27,37 @@ namespace Castle.DynamicProxy.Generators.Emitters [DebuggerDisplay("{builder.Name}")] internal class MethodEmitter : IMemberEmitter { + private readonly ProxyGenerationContext context; private readonly MethodBuilder builder; private readonly CodeBuilder codeBuilder; private readonly GenericTypeParameterBuilder[] genericTypeParams; private ArgumentReference[] arguments; - protected internal MethodEmitter(MethodBuilder builder) + protected internal MethodEmitter(ProxyGenerationContext context, MethodBuilder builder) { + this.context = context; this.builder = builder; codeBuilder = new CodeBuilder(); } - internal MethodEmitter(AbstractTypeEmitter owner, string name, MethodAttributes attributes) - : this(owner.TypeBuilder.DefineMethod(name, attributes)) + internal MethodEmitter(ProxyGenerationContext context, AbstractTypeEmitter owner, string name, MethodAttributes attributes) + : this(context, owner.TypeBuilder.DefineMethod(name, attributes)) { } - internal MethodEmitter(AbstractTypeEmitter owner, string name, + internal MethodEmitter(ProxyGenerationContext context, AbstractTypeEmitter owner, string name, MethodAttributes attributes, Type returnType, params Type[] argumentTypes) - : this(owner, name, attributes) + : this(context, owner, name, attributes) { SetParameters(argumentTypes); SetReturnType(returnType); } - internal MethodEmitter(AbstractTypeEmitter owner, string name, + internal MethodEmitter(ProxyGenerationContext context, AbstractTypeEmitter owner, string name, MethodAttributes attributes, MethodInfo methodToUseAsATemplate) - : this(owner, name, attributes) + : this(context, owner, name, attributes) { var name2GenericType = GenericUtil.GetGenericArgumentsMap(owner); @@ -63,7 +65,7 @@ internal MethodEmitter(AbstractTypeEmitter owner, string name, var baseMethodParameters = methodToUseAsATemplate.GetParameters(); var parameters = GenericUtil.ExtractParametersTypes(baseMethodParameters, name2GenericType); - genericTypeParams = GenericUtil.CopyGenericArguments(methodToUseAsATemplate, builder, name2GenericType); + genericTypeParams = GenericUtil.CopyGenericArguments(methodToUseAsATemplate, builder, context, name2GenericType); SetParameters(parameters); SetReturnType(returnType); SetSignature(returnType, methodToUseAsATemplate.ReturnParameter, parameters, baseMethodParameters); @@ -145,7 +147,7 @@ private void DefineParameters(ParameterInfo[] parameters) foreach (var parameter in parameters) { var parameterBuilder = builder.DefineParameter(parameter.Position + 1, parameter.Attributes, parameter.Name); - foreach (var attribute in parameter.GetNonInheritableAttributes()) + foreach (var attribute in parameter.GetNonInheritableAttributes(context)) { parameterBuilder.SetCustomAttribute(attribute.Builder); } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/NestedClassEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/NestedClassEmitter.cs index 53809e46b2..173fc63854 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/NestedClassEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/NestedClassEmitter.cs @@ -20,22 +20,23 @@ namespace Castle.DynamicProxy.Generators.Emitters internal class NestedClassEmitter : AbstractTypeEmitter { - public NestedClassEmitter(AbstractTypeEmitter maintype, string name, Type baseType, Type[] interfaces) + public NestedClassEmitter(ProxyGenerationContext context, AbstractTypeEmitter maintype, string name, Type baseType, Type[] interfaces) : this( + context, maintype, CreateTypeBuilder(maintype, name, TypeAttributes.Sealed | TypeAttributes.NestedPublic | TypeAttributes.Class, baseType, interfaces)) { } - public NestedClassEmitter(AbstractTypeEmitter maintype, string name, TypeAttributes attributes, Type baseType, + public NestedClassEmitter(ProxyGenerationContext context, AbstractTypeEmitter maintype, string name, TypeAttributes attributes, Type baseType, Type[] interfaces) - : this(maintype, CreateTypeBuilder(maintype, name, attributes, baseType, interfaces)) + : this(context, maintype, CreateTypeBuilder(maintype, name, attributes, baseType, interfaces)) { } - public NestedClassEmitter(AbstractTypeEmitter maintype, TypeBuilder typeBuilder) - : base(typeBuilder) + public NestedClassEmitter(ProxyGenerationContext context, AbstractTypeEmitter maintype, TypeBuilder typeBuilder) + : base(context, typeBuilder) { maintype.AddNestedClass(this); } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs index c2674b3dea..96f18bc593 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs @@ -20,14 +20,16 @@ namespace Castle.DynamicProxy.Generators.Emitters internal class PropertyEmitter : IMemberEmitter { + private readonly ProxyGenerationContext context; private readonly PropertyBuilder builder; private readonly AbstractTypeEmitter parentTypeEmitter; private MethodEmitter getMethod; private MethodEmitter setMethod; - public PropertyEmitter(AbstractTypeEmitter parentTypeEmitter, string name, PropertyAttributes attributes, + public PropertyEmitter(ProxyGenerationContext context, AbstractTypeEmitter parentTypeEmitter, string name, PropertyAttributes attributes, Type propertyType, Type[] arguments) { + this.context = context; this.parentTypeEmitter = parentTypeEmitter; builder = parentTypeEmitter.TypeBuilder.DefineProperty( @@ -53,7 +55,7 @@ public MethodEmitter CreateGetMethod(string name, MethodAttributes attrs, Method throw new InvalidOperationException("A get method exists"); } - getMethod = new MethodEmitter(parentTypeEmitter, name, attrs, methodToOverride); + getMethod = new MethodEmitter(context, parentTypeEmitter, name, attrs, methodToOverride); return getMethod; } @@ -70,7 +72,7 @@ public MethodEmitter CreateSetMethod(string name, MethodAttributes attrs, Method throw new InvalidOperationException("A set method exists"); } - setMethod = new MethodEmitter(parentTypeEmitter, name, attrs, methodToOverride); + setMethod = new MethodEmitter(context, parentTypeEmitter, name, attrs, methodToOverride); return setMethod; } diff --git a/src/Castle.Core/DynamicProxy/Generators/InheritanceInvocationTypeGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/InheritanceInvocationTypeGenerator.cs index b02d5876e9..309e42609a 100644 --- a/src/Castle.Core/DynamicProxy/Generators/InheritanceInvocationTypeGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/InheritanceInvocationTypeGenerator.cs @@ -26,9 +26,9 @@ internal class InheritanceInvocationTypeGenerator : InvocationTypeGenerator { public static readonly Type BaseType = typeof(InheritanceInvocation); - public InheritanceInvocationTypeGenerator(Type targetType, MetaMethod method, MethodInfo callback, + public InheritanceInvocationTypeGenerator(ProxyGenerationContext context, Type targetType, MetaMethod method, MethodInfo callback, IInvocationCreationContributor contributor) - : base(targetType, method, callback, false, contributor) + : base(context, targetType, method, callback, false, contributor) { } diff --git a/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetGenerator.cs index dc4ac91c41..8b4fc4ae03 100644 --- a/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetGenerator.cs @@ -23,9 +23,9 @@ namespace Castle.DynamicProxy.Generators internal sealed class InterfaceProxyWithTargetGenerator : BaseInterfaceProxyGenerator { - public InterfaceProxyWithTargetGenerator(ModuleScope scope, Type targetType, Type[] interfaces, - Type proxyTargetType, ProxyGenerationOptions options) - : base(scope, targetType, interfaces, proxyTargetType, options) + public InterfaceProxyWithTargetGenerator(ProxyGenerationContext context, ModuleScope scope, + Type targetType, Type[] interfaces, Type proxyTargetType) + : base(context, scope, targetType, interfaces, proxyTargetType) { } protected override bool AllowChangeTarget => false; @@ -34,7 +34,7 @@ public InterfaceProxyWithTargetGenerator(ModuleScope scope, Type targetType, Typ protected override CompositeTypeContributor GetProxyTargetContributor(Type proxyTargetType, INamingScope namingScope) { - return new InterfaceProxyTargetContributor(proxyTargetType, AllowChangeTarget, namingScope) { Logger = Logger }; + return new InterfaceProxyTargetContributor(Context, namingScope, proxyTargetType, AllowChangeTarget); } protected override ProxyTargetAccessorContributor GetProxyTargetAccessorContributor() diff --git a/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetInterfaceGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetInterfaceGenerator.cs index 9ae7b102c9..d7c8b27a21 100644 --- a/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetInterfaceGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetInterfaceGenerator.cs @@ -26,9 +26,9 @@ namespace Castle.DynamicProxy.Generators internal sealed class InterfaceProxyWithTargetInterfaceGenerator : BaseInterfaceProxyGenerator { - public InterfaceProxyWithTargetInterfaceGenerator(ModuleScope scope, Type targetType, Type[] interfaces, - Type proxyTargetType, ProxyGenerationOptions options) - : base(scope, targetType, interfaces, proxyTargetType, options) + public InterfaceProxyWithTargetInterfaceGenerator(ProxyGenerationContext context, ModuleScope scope, + Type targetType, Type[] interfaces, Type proxyTargetType) + : base(context, scope, targetType, interfaces, proxyTargetType) { } @@ -38,7 +38,7 @@ public InterfaceProxyWithTargetInterfaceGenerator(ModuleScope scope, Type target protected override CompositeTypeContributor GetProxyTargetContributor(Type proxyTargetType, INamingScope namingScope) { - return new InterfaceProxyWithTargetInterfaceTargetContributor(proxyTargetType, AllowChangeTarget, namingScope) { Logger = Logger }; + return new InterfaceProxyWithTargetInterfaceTargetContributor(Context, namingScope, proxyTargetType, AllowChangeTarget); } protected override ProxyTargetAccessorContributor GetProxyTargetAccessorContributor() @@ -57,8 +57,7 @@ protected override void AddMappingForAdditionalInterfaces(CompositeTypeContribut protected override InterfaceProxyWithoutTargetContributor GetContributorForAdditionalInterfaces( INamingScope namingScope) { - return new InterfaceProxyWithOptionalTargetContributor(namingScope, GetTargetExpression, GetTarget) - { Logger = Logger }; + return new InterfaceProxyWithOptionalTargetContributor(Context, namingScope, GetTargetExpression, GetTarget); } private Reference GetTarget(ClassEmitter @class, MethodInfo method) diff --git a/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithoutTargetGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithoutTargetGenerator.cs index d916e4dc62..40e598fc05 100644 --- a/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithoutTargetGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithoutTargetGenerator.cs @@ -23,9 +23,9 @@ namespace Castle.DynamicProxy.Generators internal sealed class InterfaceProxyWithoutTargetGenerator : BaseInterfaceProxyGenerator { - public InterfaceProxyWithoutTargetGenerator(ModuleScope scope, Type targetType, Type[] interfaces, - Type proxyTargetType, ProxyGenerationOptions options) - : base(scope, targetType, interfaces, proxyTargetType, options) + public InterfaceProxyWithoutTargetGenerator(ProxyGenerationContext context, ModuleScope scope, + Type targetType, Type[] interfaces, Type proxyTargetType) + : base(context, scope, targetType, interfaces, proxyTargetType) { } @@ -35,7 +35,7 @@ public InterfaceProxyWithoutTargetGenerator(ModuleScope scope, Type targetType, protected override CompositeTypeContributor GetProxyTargetContributor(Type proxyTargetType, INamingScope namingScope) { - return new InterfaceProxyWithoutTargetContributor(namingScope, (c, m) => NullExpression.Instance) { Logger = Logger }; + return new InterfaceProxyWithoutTargetContributor(Context, namingScope, (c, m) => NullExpression.Instance); } protected override ProxyTargetAccessorContributor GetProxyTargetAccessorContributor() diff --git a/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs index 133d9d77da..28c203f885 100644 --- a/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs @@ -26,15 +26,17 @@ namespace Castle.DynamicProxy.Generators internal abstract class InvocationTypeGenerator : IGenerator { + private readonly ProxyGenerationContext context; protected readonly MetaMethod method; protected readonly Type targetType; private readonly MethodInfo callback; private readonly bool canChangeTarget; private readonly IInvocationCreationContributor contributor; - protected InvocationTypeGenerator(Type targetType, MetaMethod method, MethodInfo callback, bool canChangeTarget, + protected InvocationTypeGenerator(ProxyGenerationContext context, Type targetType, MetaMethod method, MethodInfo callback, bool canChangeTarget, IInvocationCreationContributor contributor) { + this.context = context; this.targetType = targetType; this.method = method; this.callback = callback; @@ -42,6 +44,11 @@ protected InvocationTypeGenerator(Type targetType, MetaMethod method, MethodInfo this.contributor = contributor; } + protected ProxyGenerationContext Context + { + get { return context; } + } + /// /// Generates the constructor for the class that extends /// @@ -260,7 +267,7 @@ private AbstractTypeEmitter GetEmitter(ClassEmitter @class, Type[] interfaces, I 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); + return new ClassEmitter(context, @class.ModuleScope, uniqueName, GetBaseType(), interfaces, ClassEmitter.DefaultAttributes, forceUnsigned: @class.InStrongNamedModule == false); } private void ImplemementInvokeMethodOnTarget(AbstractTypeEmitter invocation, ParameterInfo[] parameters, diff --git a/src/Castle.Core/DynamicProxy/Internal/AttributeUtil.cs b/src/Castle.Core/DynamicProxy/Internal/AttributeUtil.cs index e773080c6b..4452e78dbe 100644 --- a/src/Castle.Core/DynamicProxy/Internal/AttributeUtil.cs +++ b/src/Castle.Core/DynamicProxy/Internal/AttributeUtil.cs @@ -19,6 +19,8 @@ namespace Castle.DynamicProxy.Internal using System.Diagnostics; using System.Linq; using System.Reflection; + using System.Runtime.InteropServices; + using System.Security.Permissions; using Castle.DynamicProxy.Generators; @@ -116,7 +118,7 @@ private static void GetSettersAndFields(Type attributeType, IEnumerable GetNonInheritableAttributes(this MemberInfo member) + public static IEnumerable GetNonInheritableAttributes(this MemberInfo member, ProxyGenerationContext context) { Debug.Assert(member != null, "member != null"); var attributes = member.CustomAttributes; @@ -124,7 +126,7 @@ public static IEnumerable GetNonInheritableAttributes(this foreach (var attribute in attributes) { var attributeType = attribute.AttributeType; - if (ShouldSkipAttributeReplication(attributeType, ignoreInheritance: false)) + if (ShouldSkipAttributeReplication(attributeType, ignoreInheritance: false, context)) { continue; } @@ -139,11 +141,11 @@ public static IEnumerable GetNonInheritableAttributes(this var message = string.Format( "Due to limitations in CLR, DynamicProxy was unable to successfully replicate non-inheritable attribute {0} on {1}{2}. " + - "To avoid this error you can chose not to replicate this attribute type by calling '{3}.Add(typeof({0}))'.", + "To avoid this error you can chose not to replicate this attribute type by calling 'proxyGenerationOptions.{3}.Add(typeof({0}))'.", attributeType.FullName, member.DeclaringType.FullName, (member is TypeInfo) ? "" : ("." + member.Name), - typeof(AttributesToAvoidReplicating).FullName); + nameof(ProxyGenerationOptions.AttributesToAvoidReplicating)); throw new NotSupportedException(message, e); } if (info != null) @@ -153,7 +155,7 @@ public static IEnumerable GetNonInheritableAttributes(this } } - public static IEnumerable GetNonInheritableAttributes(this ParameterInfo parameter) + public static IEnumerable GetNonInheritableAttributes(this ParameterInfo parameter, ProxyGenerationContext context) { Debug.Assert(parameter != null, "parameter != null"); @@ -165,7 +167,7 @@ public static IEnumerable GetNonInheritableAttributes(this { var attributeType = attribute.AttributeType; - if (ShouldSkipAttributeReplication(attributeType, ignoreInheritance)) + if (ShouldSkipAttributeReplication(attributeType, ignoreInheritance, context)) { continue; } @@ -183,14 +185,26 @@ public static IEnumerable GetNonInheritableAttributes(this /// but there are some special cases where the attributes means /// something to the CLR, where they should be skipped. /// - private static bool ShouldSkipAttributeReplication(Type attribute, bool ignoreInheritance) + private static bool ShouldSkipAttributeReplication(Type attribute, bool ignoreInheritance, ProxyGenerationContext context) { if (attribute.IsPublic == false) { return true; } - if (AttributesToAvoidReplicating.ShouldAvoid(attribute)) + if (attribute == typeof(ComImportAttribute) || + attribute == typeof(MarshalAsAttribute) || + attribute == typeof(TypeIdentifierAttribute)) + { + return true; + } + + if (attribute.IsSubclassOf(typeof(SecurityAttribute))) + { + return true; + } + + if (context.AttributesToAvoidReplicating.Any(a => a.IsAssignableFrom(attribute))) { return true; } diff --git a/src/Castle.Core/DynamicProxy/ProxyGenerationContext.cs b/src/Castle.Core/DynamicProxy/ProxyGenerationContext.cs new file mode 100644 index 0000000000..e69470ed65 --- /dev/null +++ b/src/Castle.Core/DynamicProxy/ProxyGenerationContext.cs @@ -0,0 +1,45 @@ +// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Castle.DynamicProxy +{ + using System; + using System.Collections.Generic; + + using Castle.Core.Logging; + + internal sealed class ProxyGenerationContext + { + public ProxyGenerationContext(ProxyGenerationOptions options, + ILogger logger = null) + { + Logger = logger ?? NullLogger.Instance; + + Options = options ?? ProxyGenerationOptions.Default; + Options.Initialize(); + + AttributesToAvoidReplicating = Options.AttributesToAvoidReplicating; + + Hook = Options.Hook ?? new AllMethodsHook(); + } + + public ISet AttributesToAvoidReplicating { get; } + + public IProxyGenerationHook Hook { get; } + + public ProxyGenerationOptions Options { get; } + + public ILogger Logger { get; } + } +} diff --git a/src/Castle.Core/DynamicProxy/ProxyGenerationOptions.cs b/src/Castle.Core/DynamicProxy/ProxyGenerationOptions.cs index 515de4bef0..e338f60edd 100644 --- a/src/Castle.Core/DynamicProxy/ProxyGenerationOptions.cs +++ b/src/Castle.Core/DynamicProxy/ProxyGenerationOptions.cs @@ -45,6 +45,7 @@ public class ProxyGenerationOptions private List mixins; private readonly IList additionalAttributes = new List(); + private readonly HashSet attributesToAvoidReplicating = new HashSet(); #if FEATURE_SERIALIZATION [NonSerialized] @@ -76,6 +77,7 @@ private ProxyGenerationOptions(SerializationInfo info, StreamingContext context) Selector = (IInterceptorSelector)info.GetValue("selector", typeof(IInterceptorSelector)); mixins = (List)info.GetValue("mixins", typeof(List)); BaseTypeForInterfaceProxy = Type.GetType(info.GetString("baseTypeForInterfaceProxy.AssemblyQualifiedName")); + attributesToAvoidReplicating = (HashSet)info.GetValue("attributesToAvoidReplicating", typeof(HashSet)); } #endif @@ -102,6 +104,7 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) info.AddValue("selector", Selector); info.AddValue("mixins", mixins); info.AddValue("baseTypeForInterfaceProxy.AssemblyQualifiedName", BaseTypeForInterfaceProxy.AssemblyQualifiedName); + info.AddValue("attributesToAvoidReplicating", attributesToAvoidReplicating); } #endif @@ -149,6 +152,14 @@ public IList AdditionalAttributes get { return additionalAttributes; } } + /// + /// Gets the set of types that should not be replicated on proxies. + /// + public ISet AttributesToAvoidReplicating + { + get { return attributesToAvoidReplicating; } + } + public MixinData MixinData { get @@ -281,6 +292,10 @@ public override bool Equals(object obj) { return false; } + if (!AttributesToAvoidReplicating.SetEquals(proxyGenerationOptions.AttributesToAvoidReplicating)) + { + return false; + } return true; } @@ -294,6 +309,7 @@ public override int GetHashCode() result = 29*result + MixinData.GetHashCode(); result = 29*result + (BaseTypeForInterfaceProxy != null ? BaseTypeForInterfaceProxy.GetHashCode() : 0); result = 29*result + GetAdditionalAttributesHashCode(); + result = 29*result + AttributesToAvoidReplicating.Count.GetHashCode(); return result; } diff --git a/src/Castle.Core/DynamicProxy/Serialization/ProxyObjectReference.cs b/src/Castle.Core/DynamicProxy/Serialization/ProxyObjectReference.cs index 461715ee97..8852051e60 100644 --- a/src/Castle.Core/DynamicProxy/Serialization/ProxyObjectReference.cs +++ b/src/Castle.Core/DynamicProxy/Serialization/ProxyObjectReference.cs @@ -131,7 +131,8 @@ protected virtual object RecreateProxy() private object RecreateClassProxyWithTarget() { - var generator = new ClassProxyWithTargetGenerator(scope, baseType, interfaces, proxyGenerationOptions); + var context = new ProxyGenerationContext(proxyGenerationOptions); + var generator = new ClassProxyWithTargetGenerator(context, scope, baseType, interfaces); var proxyType = generator.GetProxyType(); return InstantiateClassProxy(proxyType); } @@ -141,18 +142,20 @@ public object RecreateInterfaceProxy(string generatorType) var @interface = DeserializeTypeFromString("__theInterface"); var targetType = DeserializeTypeFromString("__targetFieldType"); + var context = new ProxyGenerationContext(proxyGenerationOptions); + BaseInterfaceProxyGenerator generator; if (generatorType == ProxyTypeConstants.InterfaceWithTarget) { - generator = new InterfaceProxyWithTargetGenerator(scope, @interface, interfaces, targetType, proxyGenerationOptions); + generator = new InterfaceProxyWithTargetGenerator(context, scope, @interface, interfaces, targetType); } else if (generatorType == ProxyTypeConstants.InterfaceWithoutTarget) { - generator = new InterfaceProxyWithoutTargetGenerator(scope, @interface, interfaces, targetType, proxyGenerationOptions); + generator = new InterfaceProxyWithoutTargetGenerator(context, scope, @interface, interfaces, targetType); } else if (generatorType == ProxyTypeConstants.InterfaceWithTargetInterface) { - generator = new InterfaceProxyWithTargetInterfaceGenerator(scope, @interface, interfaces, targetType, proxyGenerationOptions); + generator = new InterfaceProxyWithTargetInterfaceGenerator(context, scope, @interface, interfaces, targetType); } else { @@ -168,7 +171,8 @@ public object RecreateInterfaceProxy(string generatorType) public object RecreateClassProxy() { - var generator = new ClassProxyGenerator(scope, baseType, interfaces, proxyGenerationOptions); + var context = new ProxyGenerationContext(proxyGenerationOptions); + var generator = new ClassProxyGenerator(context, scope, baseType, interfaces); var proxyType = generator.GetProxyType(); return InstantiateClassProxy(proxyType); }