diff --git a/src/Spring/Spring.Aop/Aop/Support/AttributeMatchMethodPointcut.cs b/src/Spring/Spring.Aop/Aop/Support/AttributeMatchMethodPointcut.cs index 2c4999ba..0ba11b8a 100644 --- a/src/Spring/Spring.Aop/Aop/Support/AttributeMatchMethodPointcut.cs +++ b/src/Spring/Spring.Aop/Aop/Support/AttributeMatchMethodPointcut.cs @@ -1,203 +1,213 @@ -#region License - -/* -* Copyright 2002-2004 the original author or authors. -* -* 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. -*/ - -#endregion - -#region Imports - -using System; -using System.Reflection; -using Spring.Util; - -#endregion - -namespace Spring.Aop.Support -{ - /// - /// implementation that matches methods - /// that have been decorated with a specified . - /// - /// Aleksandar Seovic - /// Ronald Wildenberg - [Serializable] - public class AttributeMatchMethodPointcut : StaticMethodMatcherPointcut - { - private Type _attribute; - private bool _inherit = true; - private bool _checkInterfaces = false; - - /// - /// Creates a new instance of the - /// class. - /// - public AttributeMatchMethodPointcut() - { - } - - /// - /// Creates a new instance of the - /// class. - /// - /// - /// The to match. - /// - public AttributeMatchMethodPointcut(Type attribute) - : this(attribute, true, false) - { - } - - /// - /// Creates a new instance of the - /// - /// class. - /// - /// - /// The to match. - /// - /// - /// Flag that controls whether or not the inheritance tree of the - /// method to be included in the search for the ? - /// - public AttributeMatchMethodPointcut(Type attribute, bool inherit) - : this(attribute, inherit, false) - { - } - - /// - /// Creates a new instance of the - /// - /// class. - /// - /// - /// The to match. - /// - /// - /// Flag that controls whether or not the inheritance tree of the - /// method to be included in the search for the ? - /// - /// - /// Flag that controls whether or not interfaces attributes of the - /// method to be included in the search for the ? - /// - public AttributeMatchMethodPointcut(Type attribute, bool inherit, bool checkInterfaces) - { - Attribute = attribute; - Inherit = inherit; - CheckInterfaces = checkInterfaces; - } - - /// - /// The to match. - /// - /// - /// If the supplied value is not a that - /// derives from the class. - /// - public virtual Type Attribute - { - get { return _attribute; } - set - { - if (value != null) - { - if (!typeof (Attribute).IsAssignableFrom(value)) - { - throw new ArgumentException( - string.Format( - "The [{0}] Type must be derived from the [System.Attribute] class.", - value)); - } - } - _attribute = value; - } - } - - /// - /// Is the inheritance tree of the method to be included in the search for the - /// ? - /// - /// - ///

- /// The default is . - ///

- ///
- public virtual bool Inherit - { - get { return _inherit; } - set { _inherit = value; } - } - - /// - /// Is the interfaces attributes of the method to be included in the search for theg - /// ? - /// - /// - ///

- /// The default is . - ///

- ///
- public virtual bool CheckInterfaces - { - get { return _checkInterfaces; } - set { _checkInterfaces = value; } - } - - /// - /// Does the supplied satisfy this matcher? - /// - /// The candidate method. - /// - /// The target (may be , - /// in which case the candidate must be taken - /// to be the 's declaring class). - /// - /// - /// if this this method matches statically. - /// - public override bool Matches(MethodInfo method, Type targetType) - { - if (method.IsDefined(Attribute, Inherit)) - { - // Checks whether the attribute is defined on the method or a super definition of the method - // but does not check attributes on implemented interfaces. - return true; - } - else - { - if (CheckInterfaces) - { - Type[] parameterTypes = ReflectionUtils.GetParameterTypes(method); - - // Also check whether the attribute is defined on a method implemented from an interface. - // First find all interfaces for the type that contains the method. - // Next, check each interface for the presence of the attribute on the corresponding - // method from the interface. - foreach (Type interfaceType in method.DeclaringType.GetInterfaces()) - { - MethodInfo intfMethod = interfaceType.GetMethod(method.Name, parameterTypes); - if (intfMethod != null && intfMethod.IsDefined(Attribute, Inherit)) - { - return true; - } - } - } - return false; - } - } - } +#region License + +/* +* Copyright 2002-2004 the original author or authors. +* +* 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. +*/ + +#endregion + +#region Imports + +using System; +using System.Reflection; +using Spring.Util; + +#endregion + +namespace Spring.Aop.Support +{ + /// + /// implementation that matches methods + /// that have been decorated with a specified . + /// + /// Aleksandar Seovic + /// Ronald Wildenberg + [Serializable] + public class AttributeMatchMethodPointcut : StaticMethodMatcherPointcut + { + private Type _attribute; + private bool _inherit = true; + private bool _checkInterfaces = false; + + /// + /// Creates a new instance of the + /// class. + /// + public AttributeMatchMethodPointcut() + { + } + + /// + /// Creates a new instance of the + /// class. + /// + /// + /// The to match. + /// + public AttributeMatchMethodPointcut(Type attribute) + : this(attribute, true, false) + { + } + + /// + /// Creates a new instance of the + /// + /// class. + /// + /// + /// The to match. + /// + /// + /// Flag that controls whether or not the inheritance tree of the + /// method to be included in the search for the ? + /// + public AttributeMatchMethodPointcut(Type attribute, bool inherit) + : this(attribute, inherit, false) + { + } + + /// + /// Creates a new instance of the + /// + /// class. + /// + /// + /// The to match. + /// + /// + /// Flag that controls whether or not the inheritance tree of the + /// method to be included in the search for the ? + /// + /// + /// Flag that controls whether or not interfaces attributes of the + /// method to be included in the search for the ? + /// + public AttributeMatchMethodPointcut(Type attribute, bool inherit, bool checkInterfaces) + { + Attribute = attribute; + Inherit = inherit; + CheckInterfaces = checkInterfaces; + } + + /// + /// The to match. + /// + /// + /// If the supplied value is not a that + /// derives from the class. + /// + public virtual Type Attribute + { + get { return _attribute; } + set + { + if (value != null) + { + if (!typeof (Attribute).IsAssignableFrom(value)) + { + throw new ArgumentException( + string.Format( + "The [{0}] Type must be derived from the [System.Attribute] class.", + value)); + } + } + _attribute = value; + } + } + + /// + /// Is the inheritance tree of the method to be included in the search for the + /// ? + /// + /// + ///

+ /// The default is . + ///

+ ///
+ public virtual bool Inherit + { + get { return _inherit; } + set { _inherit = value; } + } + + /// + /// Is the interfaces attributes of the method to be included in the search for theg + /// ? + /// + /// + ///

+ /// The default is . + ///

+ ///
+ public virtual bool CheckInterfaces + { + get { return _checkInterfaces; } + set { _checkInterfaces = value; } + } + + /// + /// Does the supplied satisfy this matcher? + /// + /// The candidate method. + /// + /// The target (may be , + /// in which case the candidate must be taken + /// to be the 's declaring class). + /// + /// + /// if this this method matches statically. + /// + public override bool Matches(MethodInfo method, Type targetType) + { + if (method.IsDefined(Attribute, Inherit)) + { + // Checks whether the attribute is defined on the method or a super definition of the method + // but does not check attributes on implemented interfaces. + return true; + } + else + { + if (CheckInterfaces) + { + // Also check whether the attribute is defined on a method implemented from an interface. + // First find all interfaces for the type that contains the method. + // Next, check each interface for the presence of the attribute on the corresponding + // method from the interface. + Type[] parameterTypes = ReflectionUtils.GetParameterTypes(method); + foreach (Type interfaceType in method.DeclaringType.GetInterfaces()) + { + // The method may be implemented explicitly, so the method name + // will include the interface name also + string methodName = method.Name; + if (methodName.IndexOf('.') != -1) + { + if (methodName.StartsWith(interfaceType.FullName.Replace('+', '.'))) + { + methodName = methodName.Remove(0, interfaceType.FullName.Length + 1); + } + } + + MethodInfo intfMethod = interfaceType.GetMethod(methodName, parameterTypes); + if (intfMethod != null && intfMethod.IsDefined(Attribute, Inherit)) + { + return true; + } + } + } + return false; + } + } + } } \ No newline at end of file diff --git a/test/Spring/Spring.Aop.Tests/Aop/Support/AttributeMatchMethodPointcutTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Support/AttributeMatchMethodPointcutTests.cs index 690ca913..a42f5594 100644 --- a/test/Spring/Spring.Aop.Tests/Aop/Support/AttributeMatchMethodPointcutTests.cs +++ b/test/Spring/Spring.Aop.Tests/Aop/Support/AttributeMatchMethodPointcutTests.cs @@ -179,6 +179,26 @@ namespace Spring.Aop.Support "but the method from an indirectly implemented interface was, so this must match."); } + /// + /// Confirms that methods, explicitly implemented in the derived classes will match + /// + [Test(Description="SPRNET-1314")] + public void MatchesWhenExplicitlyImplemed() + { + AttributeMatchMethodPointcut cut = new AttributeMatchMethodPointcut(); + cut.Attribute = typeof(MarkupAttribute); + cut.CheckInterfaces = true; + + // Only methods implemented expicitly are marked with attribute + foreach (MethodInfo mi in typeof(ExplicitlyImplementingClass).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)) + { + if (mi.Name.IndexOf('.') == -1) continue; + bool matches = cut.Matches(mi, null); + Assert.IsTrue(matches, "Explicitly implemented method must match"); + } + + } + #region Helper classes definitions [AttributeUsage(AttributeTargets.Method)] @@ -210,6 +230,12 @@ namespace Spring.Aop.Support void OtherTestMethod(); } + private interface AnotherSuperInterface + { + [Markup] + void TestMethod(); + } + private class ImplementingClass : SubInterface { public void TestMethod() {} @@ -223,6 +249,15 @@ namespace Spring.Aop.Support { } + private class ExplicitlyImplementingClass : SuperInterface, AnotherSuperInterface + { + void AnotherSuperInterface.TestMethod() { } + + void SuperInterface.TestMethod() { } + + public void TestMethod(string param) {} + } + #endregion } } \ No newline at end of file