diff --git a/src/Spring/Spring.Aop/Aspects/Cache/CacheParameterAdvice.cs b/src/Spring/Spring.Aop/Aspects/Cache/CacheParameterAdvice.cs
index 713b345c..19f697d0 100644
--- a/src/Spring/Spring.Aop/Aspects/Cache/CacheParameterAdvice.cs
+++ b/src/Spring/Spring.Aop/Aspects/Cache/CacheParameterAdvice.cs
@@ -121,26 +121,33 @@ namespace Spring.Aspects.Cache
CacheParameterInfo cpi = GetCacheParameterInfo(method);
CacheParameterAttribute[][] cacheParameterAttributes = cpi.CacheParameterAttributes;
- for (int i = 0; i < cacheParameterAttributes.Length; i++)
- {
- foreach (CacheParameterAttribute paramInfo in cacheParameterAttributes[i])
- {
- if (EvalCondition(paramInfo.Condition, paramInfo.ConditionExpression, arguments[i], null))
- {
- ICache cache = GetCache(paramInfo.CacheName);
-
- object key = paramInfo.KeyExpression.GetValue(arguments[i]);
-
- #region Instrumentation
- if (isLogDebugEnabled)
- {
- logger.Debug(string.Format("Caching parameter for key [{0}] into cache [{1}].", key, paramInfo.CacheName));
- }
- #endregion
-
- cache.Insert(key, arguments[i], paramInfo.TimeToLiveTimeSpan);
- }
- }
+ if (cacheParameterAttributes.Length > 0)
+ {
+ IDictionary vars = PrepareVariables(method, arguments);
+ for (int i = 0; i < cacheParameterAttributes.Length; i++)
+ {
+ foreach (CacheParameterAttribute paramInfo in cacheParameterAttributes[i])
+ {
+ AssertUtils.ArgumentNotNull(paramInfo.KeyExpression, "Key",
+ "The cache attribute is missing the key definition.");
+
+ if (EvalCondition(paramInfo.Condition, paramInfo.ConditionExpression, arguments[i], vars))
+ {
+ ICache cache = GetCache(paramInfo.CacheName);
+
+ object key = paramInfo.KeyExpression.GetValue(arguments[i], vars);
+
+ #region Instrumentation
+ if (isLogDebugEnabled)
+ {
+ logger.Debug(string.Format("Caching parameter for key [{0}] into cache [{1}].", key, paramInfo.CacheName));
+ }
+ #endregion
+
+ cache.Insert(key, arguments[i], paramInfo.TimeToLiveTimeSpan);
+ }
+ }
+ }
}
}
}
diff --git a/src/Spring/Spring.Aop/Aspects/Cache/CacheResultAdvice.cs b/src/Spring/Spring.Aop/Aspects/Cache/CacheResultAdvice.cs
index f7cb963f..a6883095 100644
--- a/src/Spring/Spring.Aop/Aspects/Cache/CacheResultAdvice.cs
+++ b/src/Spring/Spring.Aop/Aspects/Cache/CacheResultAdvice.cs
@@ -118,12 +118,15 @@ namespace Spring.Aspects.Cache
{
CacheResultInfo cacheResultInfo = GetCacheResultInfo(invocation.Method);
+ // prepare variables for SpEL expressions
+ IDictionary vars = PrepareVariables(invocation.Method, invocation.Arguments);
+
bool cacheHit = false;
- object returnValue = GetReturnValue(invocation, cacheResultInfo.ResultInfo, out cacheHit);
+ object returnValue = GetReturnValue(invocation, cacheResultInfo.ResultInfo, vars, out cacheHit);
if (!cacheHit && cacheResultInfo.ItemInfoArray.Length > 0 && returnValue is IEnumerable)
{
- CacheResultItems((IEnumerable)returnValue, cacheResultInfo.ItemInfoArray);
+ CacheResultItems((IEnumerable)returnValue, cacheResultInfo.ItemInfoArray, vars);
}
return returnValue;
@@ -141,13 +144,16 @@ namespace Spring.Aspects.Cache
/// in which case no caching of the result as a whole will be performed
/// (if the result is collection, individual items could still be cached separately).
///
+ ///
+ /// Variables for expression evaluation.
+ ///
///
/// Returns true if the return value was found in cache, false otherwise.
///
///
/// Return value for the specified .
///
- private object GetReturnValue(IMethodInvocation invocation, CacheResultAttribute resultInfo, out bool cacheHit)
+ private object GetReturnValue(IMethodInvocation invocation, CacheResultAttribute resultInfo, IDictionary vars, out bool cacheHit)
{
if (resultInfo != null)
{
@@ -155,15 +161,13 @@ namespace Spring.Aspects.Cache
bool isLogDebugEnabled = logger.IsDebugEnabled;
#endregion
+ AssertUtils.ArgumentNotNull(resultInfo.KeyExpression, "Key",
+ "The cache attribute is missing the key definition.");
+
object returnValue = null;
-
- IDictionary vars = PrepareVariables(invocation.Method, invocation.Arguments);
-
- AssertUtils.ArgumentNotNull(resultInfo.KeyExpression, "KeyExpression",
- "The cache attribute is missing the key definition.");
object resultKey = resultInfo.KeyExpression.GetValue(null, vars);
+
ICache cache = GetCache(resultInfo.CacheName);
-
returnValue = cache.Get(resultKey);
cacheHit = (returnValue != null);
if (!cacheHit)
@@ -213,12 +217,15 @@ namespace Spring.Aspects.Cache
///
/// Attributes specifying where and how to cache each item from the collection.
///
- private void CacheResultItems(IEnumerable items, CacheResultItemsAttribute[] itemInfoArray)
+ ///
+ /// Variables for expression evaluation.
+ ///
+ private void CacheResultItems(IEnumerable items, CacheResultItemsAttribute[] itemInfoArray, IDictionary vars)
{
foreach (CacheResultItemsAttribute itemInfo in itemInfoArray)
{
- AssertUtils.ArgumentNotNull(itemInfo.KeyExpression, "KeyExpression",
- "The cache attribute is missing the key definition.");
+ AssertUtils.ArgumentNotNull(itemInfo.KeyExpression, "Key",
+ "The cache attribute is missing the key definition.");
ICache cache = GetCache(itemInfo.CacheName);
@@ -227,9 +234,9 @@ namespace Spring.Aspects.Cache
#endregion
foreach (object item in items)
{
- if (EvalCondition(itemInfo.Condition, itemInfo.ConditionExpression, item, null))
+ if (EvalCondition(itemInfo.Condition, itemInfo.ConditionExpression, item, vars))
{
- object itemKey = itemInfo.KeyExpression.GetValue(item);
+ object itemKey = itemInfo.KeyExpression.GetValue(item, vars);
#region Instrumentation
if (isDebugEnabled)
{
diff --git a/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheParameterAdviceTests.cs b/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheParameterAdviceTests.cs
index c53a6f98..8cf57214 100644
--- a/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheParameterAdviceTests.cs
+++ b/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheParameterAdviceTests.cs
@@ -72,6 +72,23 @@ namespace Spring.Aspects.Cache
mocks.VerifyAll();
}
+ [Test]
+ public void TestSimpleWithMethodInfoParameterCaching()
+ {
+ MethodInfo method = typeof(SimpleWithMethodInfoCacheParameterTarget).GetMethod("Save");
+ object[] args = new object[] { new Inventor("Nikola Tesla", new DateTime(1856, 7, 9), "Serbian") };
+
+ ExpectCacheInstanceRetrieval("cache", cache);
+ mocks.ReplayAll();
+
+ // parameter value should be added to cache
+ advice.AfterReturning(null, method, args, null);
+ Assert.AreEqual(1, cache.Count);
+ Assert.AreEqual(args[0], cache.Get("Save-Nikola Tesla"));
+
+ mocks.VerifyAll();
+ }
+
[Test]
public void TestMultipleParameterCaching()
{
@@ -126,6 +143,13 @@ namespace Spring.Aspects.Cache
}
}
+ public sealed class SimpleWithMethodInfoCacheParameterTarget : ICacheParameterTarget
+ {
+ public void Save([CacheParameter("cache", "#Save.Name + '-' + Name")] Inventor inventor)
+ {
+ }
+ }
+
public sealed class MultipleCacheParameterTarget : ICacheParameterTarget
{
public void Save([CacheParameter("cache", "Name")][CacheParameter("cache", "Nationality")] Inventor inventor)
diff --git a/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheResultAdviceTests.cs b/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheResultAdviceTests.cs
index 47da50eb..c0277455 100644
--- a/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheResultAdviceTests.cs
+++ b/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheResultAdviceTests.cs
@@ -195,6 +195,7 @@ namespace Spring.Aspects.Cache
object expectedReturnValue = new object[] { "one", "two", "three" };
ExpectAttributeRetrieval(method);
+ ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval("items", itemCache);
@@ -228,6 +229,7 @@ namespace Spring.Aspects.Cache
object expectedReturnValue = new object[] { "one", "two", "three" };
ExpectAttributeRetrieval(method);
+ ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval( "items", itemCache );
ExpectCacheInstanceRetrieval( "items", itemCache );
@@ -264,6 +266,7 @@ namespace Spring.Aspects.Cache
object expectedReturnValue = new object[] { "one", "two", "three" };
ExpectAttributeRetrieval(method);
+ ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval( "items", itemCache );
@@ -370,6 +373,49 @@ namespace Spring.Aspects.Cache
mockContext.Verify();
}
+ [Test]
+ public void CacheResultWithMethodInfo()
+ {
+ MethodInfo method = new EnumerableResultMethod(cacheResultTarget.CacheResultWithMethodInfo).Method;
+ object expectedReturnValue = new object[] { "one", "two", "three" };
+
+ ExpectAttributeRetrieval(method);
+ ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
+ ExpectCacheInstanceRetrieval("results", resultCache);
+ ExpectCallToProceed(new object[] { "one", "two", "three" });
+
+ // return value should be added to cache
+ object returnValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
+ Assert.AreEqual(expectedReturnValue, returnValue);
+ Assert.AreEqual(1, resultCache.Count);
+ Assert.AreEqual(returnValue, resultCache.Get("CacheResultWithMethodInfo-5"));
+
+ mockInvocation.Verify();
+ mockContext.Verify();
+ }
+
+ [Test]
+ public void CacheResultItemsWithMethodInfo()
+ {
+ MethodInfo method = new EnumerableResultMethod(cacheResultTarget.CacheResultItemsWithMethodInfo).Method;
+ object expectedReturnValue = new object[] { "one", "two", "three" };
+
+ ExpectAttributeRetrieval(method);
+ ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
+ ExpectCallToProceed(new object[] { "one", "two", "three" });
+ ExpectCacheInstanceRetrieval("items", itemCache);
+
+ // return value should be added to result cache and each item to item cache
+ object returnValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
+ Assert.AreEqual(expectedReturnValue, returnValue);
+ Assert.AreEqual(0, resultCache.Count);
+ Assert.AreEqual(3, itemCache.Count);
+ Assert.AreEqual("two", itemCache.Get("CacheResultItemsWithMethodInfo-two"));
+
+ mockInvocation.Verify();
+ mockContext.Verify();
+ }
+
#region Helper methods
@@ -499,6 +545,18 @@ namespace Spring.Aspects.Cache
return elements;
}
+ [CacheResult("results", "#CacheResultWithMethodInfo.Name + '-' + #key")]
+ public IEnumerable CacheResultWithMethodInfo(int key, params object[] elements)
+ {
+ return elements;
+ }
+
+ [CacheResultItems("items", "#CacheResultItemsWithMethodInfo.Name + '-' + #this")]
+ public IEnumerable CacheResultItemsWithMethodInfo(int key, params object[] elements)
+ {
+ return elements;
+ }
+
[CacheResultItems( "items", "#this", Condition = "#this.StartsWith('t')" )]
public IEnumerable CacheResultItemsWithCondition( int key, params object[] elements )
{