diff --git a/src/Spring/Spring.Aop/Aop/Support/AbstractRegularExpressionMethodPointcut.cs b/src/Spring/Spring.Aop/Aop/Support/AbstractRegularExpressionMethodPointcut.cs
index 6abb8a1e..ccb00252 100644
--- a/src/Spring/Spring.Aop/Aop/Support/AbstractRegularExpressionMethodPointcut.cs
+++ b/src/Spring/Spring.Aop/Aop/Support/AbstractRegularExpressionMethodPointcut.cs
@@ -1,5 +1,5 @@
-#region License
-
+#region License
+
/*
* Copyright © 2002-2005 the original author or authors.
*
@@ -14,97 +14,97 @@
* 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 System.Runtime.Serialization;
-using System.Security.Permissions;
-using AopAlliance.Aop;
-using Spring.Core;
-using Spring.Objects;
-using Spring.Util;
-
-#endregion
-
-namespace Spring.Aop.Support
-{
- ///
- /// Abstract base regular expression pointcut object.
- ///
- ///
- ///
- /// The regular expressions must be a match. For example, the
- /// .*Get.* pattern will match Com.Mycom.Foo.GetBar(), and
- /// Get.* will not.
- ///
- ///
- /// This base class is serializable. Subclasses should decorate all
- /// fields with the - the
- ///
- /// method in this class will be invoked again on the client side on deserialization.
- ///
- ///
- /// Rod Johnson
- /// Juergen Hoeller
- /// Simon White (.NET)
- [Serializable]
- public abstract class AbstractRegularExpressionMethodPointcut
- : StaticMethodMatcherPointcut, ITypeFilter, ISerializable
- {
- [NonSerialized]
- private object[] _patterns = ObjectUtils.EmptyObjects;
-
- #region Constructors
-
- ///
- /// Creates a new instance of the
- ///
- /// class.
- ///
- ///
- ///
- /// This is an abstract class, and as such has no publicly
- /// visible constructors.
- ///
- ///
- protected AbstractRegularExpressionMethodPointcut()
- {
- }
-
- ///
- /// Creates a new instance of the
- /// class.
- ///
- ///
- /// The
- /// that holds the serialized object data about the exception being thrown.
- ///
- ///
- /// The
- /// that contains contextual information about the source or destination.
- ///
- ///
- /// If an error was encountered during the deserialization process.
- ///
- protected AbstractRegularExpressionMethodPointcut(
- SerializationInfo info, StreamingContext context)
- {
- _patterns = (object[]) info.GetValue("Patterns", typeof(object[]));
+ */
+
+#endregion
+
+#region Imports
+
+using System;
+using System.Reflection;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using AopAlliance.Aop;
+using Spring.Core;
+using Spring.Objects;
+using Spring.Util;
+
+#endregion
+
+namespace Spring.Aop.Support
+{
+ ///
+ /// Abstract base regular expression pointcut object.
+ ///
+ ///
+ ///
+ /// The regular expressions must be a match. For example, the
+ /// .*Get.* pattern will match Com.Mycom.Foo.GetBar(), and
+ /// Get.* will not.
+ ///
+ ///
+ /// This base class is serializable. Subclasses should decorate all
+ /// fields with the - the
+ ///
+ /// method in this class will be invoked again on the client side on deserialization.
+ ///
+ ///
+ /// Rod Johnson
+ /// Juergen Hoeller
+ /// Simon White (.NET)
+ [Serializable]
+ public abstract class AbstractRegularExpressionMethodPointcut
+ : StaticMethodMatcherPointcut, ITypeFilter, ISerializable
+ {
+ [NonSerialized]
+ private object[] _patterns = ObjectUtils.EmptyObjects;
+
+ #region Constructors
+
+ ///
+ /// Creates a new instance of the
+ ///
+ /// class.
+ ///
+ ///
+ ///
+ /// This is an abstract class, and as such has no publicly
+ /// visible constructors.
+ ///
+ ///
+ protected AbstractRegularExpressionMethodPointcut()
+ {
+ }
+
+ ///
+ /// Creates a new instance of the
+ /// class.
+ ///
+ ///
+ /// The
+ /// that holds the serialized object data about the exception being thrown.
+ ///
+ ///
+ /// The
+ /// that contains contextual information about the source or destination.
+ ///
+ ///
+ /// If an error was encountered during the deserialization process.
+ ///
+ protected AbstractRegularExpressionMethodPointcut(
+ SerializationInfo info, StreamingContext context)
+ {
+ _patterns = (object[])info.GetValue("Patterns", typeof(object[]));
if (_patterns == null)
{
_patterns = ObjectUtils.EmptyObjects;
}
}
- ///
- /// Overridden to ensure proper initialization
- ///
- protected override void OnDeserialization(object sender)
+ ///
+ /// Overridden to ensure proper initialization
+ ///
+ protected override void OnDeserialization(object sender)
{
base.OnDeserialization(sender);
try
@@ -116,172 +116,184 @@ namespace Spring.Aop.Support
throw new AspectException(
"Failed to deserialize AOP regular expression pointcut: " + ex.Message);
}
- }
-
- #endregion
-
- #region Properties
-
- ///
- /// The for this pointcut.
- ///
- ///
- /// The current .
- ///
- public override ITypeFilter TypeFilter
- {
- get { return this; }
- }
-
- ///
- /// Convenience property for setting a single pattern.
- ///
- ///
- /// Use this property or Patterns, not both.
- ///
- public virtual object Pattern
- {
- get { return (_patterns.Length > 0 ? _patterns[0] : null); }
- set
- {
- AssertUtils.ArgumentNotNull(value, "Pattern");
- this.Patterns = new object[] {value};
- }
- }
-
- ///
- /// The regular expressions defining methods to match.
- ///
- ///
- /// Matching will be the union of all these; if any match,
- /// the pointcut matches.
- ///
- public virtual object[] Patterns
- {
- get { return _patterns; }
- set
- {
- AssertUtils.ArgumentNotNull(value, "Patterns");
- this._patterns = value;
- InitPatternRepresentation(this.Patterns);
- }
- }
-
- #endregion
-
- #region Methods
-
- ///
- /// Populates a with
- /// the data needed to serialize the target object.
- ///
- ///
- /// The to populate
- /// with data.
- ///
- ///
- /// The destination (see )
- /// for this serialization.
- ///
- [SecurityPermission(SecurityAction.Demand, SerializationFormatter=true)]
- public void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- info.AddValue("Patterns", _patterns);
- }
-
- ///
- /// Subclasses must implement this to initialize regular expression pointcuts.
- ///
- ///
- ///
- /// Can be invoked multiple times.
- ///
- ///
- /// This method will be invoked from the property,
- /// and also on deserialization.
- ///
- ///
- ///
- /// The patterns to initialize.
- ///
- ///
- /// In the case of an invalid pattern.
- ///
- protected abstract void InitPatternRepresentation(object[] patterns);
-
- ///
- /// Does the pattern at the supplied
- /// match this ?
- ///
- /// The pattern to match
- /// The index of pattern.
- ///
- /// if there is a match.
- ///
- protected abstract bool Matches(string pattern, int patternIndex);
-
- ///
- /// Does the supplied satisfy this matcher?
- ///
- ///
- ///
- /// Try to match the regular expression against the fully qualified name
- /// of the method's declaring , plus the name of
- /// the supplied .
- ///
- ///
- /// Note that the declaring is that
- /// that originally declared
- /// the method, not necessarily the that is
- /// currently exposing it. For example,
- /// matches any subclass of 's
- /// method.
- ///
- ///
- /// 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)
- {
- string patt = method.DeclaringType.FullName + "." + method.Name;
- for (int i = 0; i < this.Patterns.Length; ++i)
- {
- bool matched = Matches(patt, i);
- if (matched)
- {
- return true;
- }
- }
- return false;
- }
-
- ///
- /// Should the pointcut apply to the supplied
- /// ?
- ///
- ///
- ///
- /// In this instance, simply returns .
- ///
- ///
- ///
- /// The candidate .
- ///
- ///
- /// if the advice should apply to the supplied
- ///
- ///
- public bool Matches(Type type)
- {
- return true;
- }
-
- #endregion
- }
+ }
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// The for this pointcut.
+ ///
+ ///
+ /// The current .
+ ///
+ public override ITypeFilter TypeFilter
+ {
+ get { return this; }
+ }
+
+ ///
+ /// Convenience property for setting a single pattern.
+ ///
+ ///
+ /// Use this property or Patterns, not both.
+ ///
+ public virtual object Pattern
+ {
+ get { return (_patterns.Length > 0 ? _patterns[0] : null); }
+ set
+ {
+ AssertUtils.ArgumentNotNull(value, "Pattern");
+ this.Patterns = new object[] { value };
+ }
+ }
+
+ ///
+ /// The regular expressions defining methods to match.
+ ///
+ ///
+ /// Matching will be the union of all these; if any match,
+ /// the pointcut matches.
+ ///
+ public virtual object[] Patterns
+ {
+ get { return _patterns; }
+ set
+ {
+ AssertUtils.ArgumentNotNull(value, "Patterns");
+ this._patterns = value;
+ InitPatternRepresentation(this.Patterns);
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Populates a with
+ /// the data needed to serialize the target object.
+ ///
+ ///
+ /// The to populate
+ /// with data.
+ ///
+ ///
+ /// The destination (see )
+ /// for this serialization.
+ ///
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("Patterns", _patterns);
+ }
+
+ ///
+ /// Subclasses must implement this to initialize regular expression pointcuts.
+ ///
+ ///
+ ///
+ /// Can be invoked multiple times.
+ ///
+ ///
+ /// This method will be invoked from the property,
+ /// and also on deserialization.
+ ///
+ ///
+ ///
+ /// The patterns to initialize.
+ ///
+ ///
+ /// In the case of an invalid pattern.
+ ///
+ protected abstract void InitPatternRepresentation(object[] patterns);
+
+ ///
+ /// Does the pattern at the supplied
+ /// match this ?
+ ///
+ /// The pattern to match
+ /// The index of pattern.
+ ///
+ /// if there is a match.
+ ///
+ protected abstract bool Matches(string pattern, int patternIndex);
+
+ ///
+ /// Does the supplied satisfy this matcher?
+ ///
+ ///
+ ///
+ /// Try to match the regular expression against the fully qualified name
+ /// of the method's declaring , plus the name of
+ /// the supplied .
+ ///
+ ///
+ /// Note that the declaring is that
+ /// that originally declared
+ /// the method, not necessarily the that is
+ /// currently exposing it. For example,
+ /// matches any subclass of 's
+ /// method.
+ ///
+ ///
+ /// 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)
+ {
+ string patt = string.Empty;
+ patt = String.Format("{0}.{1}", method.DeclaringType, method.Name);
+
+#if NET_2_0
+ if (method.DeclaringType.IsGenericType)
+ {
+ patt = String.Format("{0}.{1}", ReflectionUtils.GetTypeFriendlyName(method.DeclaringType), method.Name);
+ }
+ else
+ {
+ patt = String.Format("{0}.{1}", method.DeclaringType, method.Name);
+ }
+#endif
+ for (int i = 0; i < this.Patterns.Length; ++i)
+ {
+ bool matched = Matches(patt, i);
+ if (matched)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Should the pointcut apply to the supplied
+ /// ?
+ ///
+ ///
+ ///
+ /// In this instance, simply returns .
+ ///
+ ///
+ ///
+ /// The candidate .
+ ///
+ ///
+ /// if the advice should apply to the supplied
+ ///
+ ///
+ public bool Matches(Type type)
+ {
+ return true;
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Util/ReflectionUtils.cs b/src/Spring/Spring.Core/Util/ReflectionUtils.cs
index 4880ba55..c30b7d97 100644
--- a/src/Spring/Spring.Core/Util/ReflectionUtils.cs
+++ b/src/Spring/Spring.Core/Util/ReflectionUtils.cs
@@ -669,6 +669,33 @@ namespace Spring.Util
return paramsType;
}
+
+ ///
+ /// Given the return its representation as
+ /// it would appear in the source code files.
+ ///
+ ///
+ /// Largely intended to handle generic types where .ToString() will typically return:
+ /// "System.Collections.Generic.List`1[System.Collections.Generic.Dictionary`2[System.String,System.Int32]]"
+ /// and this method will instead return:
+ /// "System.Collections.Generic.List<System.Collections.Generic.Dictionary<string,int>>"
+ ///
+ /// The type.
+ /// Friendly string representing the Type
+ public static string GetTypeFriendlyName(Type type)
+ {
+#if MONO
+ //no csharp services in mono (verify this!) so have to fall back to returning the ToString() for now
+ //TODO: investigate whether there is another equivalent manner of providing this functionality under MONO
+ return type.ToString();
+#endif
+#if NET_2_0
+ return (new Microsoft.CSharp.CSharpCodeProvider()).GetTypeOutput(new System.CodeDom.CodeTypeReference(type));
+#endif
+ return type.ToString();
+ }
+
+
///
/// Does the given and/or it's superclasses
/// have at least one or more methods with the given name (with any
diff --git a/test/Spring/Spring.Aop.Tests/Aop/Support/AbstractRegularExpressionMethodPointcutTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Support/AbstractRegularExpressionMethodPointcutTests.cs
index cc1684f9..04dfaef0 100644
--- a/test/Spring/Spring.Aop.Tests/Aop/Support/AbstractRegularExpressionMethodPointcutTests.cs
+++ b/test/Spring/Spring.Aop.Tests/Aop/Support/AbstractRegularExpressionMethodPointcutTests.cs
@@ -74,12 +74,46 @@ namespace Spring.Aop.Support
ExactMatchTests(pointcut);
}
- protected void ExactMatchTests(AbstractRegularExpressionMethodPointcut rpc)
- {
- // assumes rpc.setPattern("java.lang.Object.hashCode");
- Assert.IsTrue(rpc.Matches(typeof(object).GetMethod("GetHashCode"), typeof(int)));
- Assert.IsFalse(rpc.Matches(typeof(object).GetMethod("GetType"), typeof(Type)));
- }
+#if NET_2_0
+ protected void ExactMatchWithGenericTypeTests(AbstractRegularExpressionMethodPointcut rpc)
+ {
+ // assumes rpc.setPattern("System.Collections.Generic.List");
+ Assert.IsTrue(rpc.Matches(typeof(System.Collections.Generic.List).GetMethod("Add"), typeof(int)));
+ Assert.IsFalse(rpc.Matches(typeof(System.Collections.Generic.List).GetMethod("GetType"), typeof(Type)));
+ }
+
+ [Test]
+ public void ExactMatchWithGenericType()
+ {
+ pointcut.Pattern = "System.Collections.Generic.List.Add";
+ ExactMatchWithGenericTypeTests(pointcut);
+ pointcut = (AbstractRegularExpressionMethodPointcut)SerializationTestUtils.SerializeAndDeserialize(pointcut);
+ ExactMatchWithGenericTypeTests(pointcut);
+ }
+
+ [Test]
+ public void WildcardWithGenericType()
+ {
+ pointcut.Pattern = ".*List.Add";
+ Assert.IsTrue(pointcut.Matches(typeof(System.Collections.Generic.List).GetMethod("Add"), typeof(int)));
+ Assert.IsFalse(pointcut.Matches(typeof(System.Collections.Generic.List).GetMethod("GetType"), typeof(Type)));
+ }
+
+ [Test]
+ public void WildcardForOneClassWithGenericType()
+ {
+ pointcut.Pattern = "System.Collections.*";
+ Assert.IsTrue(pointcut.Matches(typeof(System.Collections.Generic.List).GetMethod("Add"), typeof(int)));
+ Assert.IsFalse(pointcut.Matches(typeof(System.Collections.Generic.List).GetMethod("GetType"), typeof(Type)));
+ }
+#endif
+
+ protected void ExactMatchTests(AbstractRegularExpressionMethodPointcut rpc)
+ {
+ // assumes rpc.setPattern("java.lang.Object.hashCode");
+ Assert.IsTrue(rpc.Matches(typeof(object).GetMethod("GetHashCode"), typeof(int)));
+ Assert.IsFalse(rpc.Matches(typeof(object).GetMethod("GetType"), typeof(Type)));
+ }
[Test]
public void Wildcard()
@@ -88,7 +122,7 @@ namespace Spring.Aop.Support
Assert.IsTrue(pointcut.Matches(typeof(object).GetMethod("GetHashCode"), typeof(int)));
Assert.IsFalse(pointcut.Matches(typeof(object).GetMethod("GetType"), typeof(Type)));
}
-
+
[Test]
public void WildcardForOneClass()
{
@@ -100,10 +134,11 @@ namespace Spring.Aop.Support
[Test]
public void MatchesObjectClass()
{
- pointcut.Pattern = "System.Object.*";
+ pointcut.Pattern = "Object.*";
Assert.IsTrue(pointcut.Matches(typeof(Exception).GetMethod("GetHashCode"), typeof(TargetException)));
// Doesn't match
Assert.IsFalse(pointcut.Matches(typeof(Exception).GetMethod("ToString"), typeof(Exception)));
}
+
}
}
diff --git a/test/Spring/Spring.Core.Tests/Util/ReflectionUtilsTests.cs b/test/Spring/Spring.Core.Tests/Util/ReflectionUtilsTests.cs
index e9d4fae6..b2b6f23c 100644
--- a/test/Spring/Spring.Core.Tests/Util/ReflectionUtilsTests.cs
+++ b/test/Spring/Spring.Core.Tests/Util/ReflectionUtilsTests.cs
@@ -1222,6 +1222,15 @@ namespace Spring.Util
Assert.AreEqual(ex, appEx);
}
+#if NET_2_0
+ [Test]
+ public void CanGetFriendlyNamesForGenericTypes()
+ {
+ Type t = typeof(System.Collections.Generic.List>);
+
+ Assert.AreEqual("System.Collections.Generic.List>", ReflectionUtils.GetTypeFriendlyName(t));
+ }
+#endif
#endregion
#region Helper Methods