问题
I am using Dynacache to cache data that will be eventually returned from a service call - to get things working I am just stubbing the data returned. I am using SimpleInjector for DI and got Dynacache registered with it as pointed out in the answer I got to a previous question
So I have an integration project within my solution which contains the method I want to cache - which currently looks as below:
[CacheableMethod(30)]
public virtual List<MyResponse> GetDataByAccountNumber(int accountNumber)
{
var response = StubResposne();
return response;
}
With implementation above Dynacache should cache the data for 30 secs and then clear it. However if I set a breakpoint on the first line in my private StubResponse() method the first time I hit the webpage which uses that data the breakpoint gets hit as expected and the data is returned. However if I refresh the page straight away again I was expecting that as the data would have been cached (as its within 30 secs) then the breakpoint would not have been hit but it is hit everytime?
Is there something incorrect with how I am using Dynacache?
回答1:
This may be due to the way you are registering the class that contains the GetDataByAccountNumber
method.
This first test works - if I call the method twice from the same instance I get the cached result back second time around
[Test]
public void GetDataByAccountNumber_CalledTwiceSameInstance_ReturnsCacheSecondTime()
{
var container = new Container();
container.Register<IDynaCacheService>(() => new MemoryCacheService());
container.Register(typeof(TestClass), Cacheable.CreateType<TestClass>());
var instance = container.GetInstance<TestClass>();
instance.GetDataByAccountNumber(1);
instance.GetDataByAccountNumber(2);
Assert.That(instance.CallerId == 1);
}
If I get 2 different instances from the container then no caching is done
public void GetDataByAccountNumber_CalledTwiceDifferentInstance_DoesNotReturnFromCache()
{
var container = new Container();
container.Register<IDynaCacheService>(() => new MemoryCacheService());
container.Register(typeof(TestClass), Cacheable.CreateType<TestClass>());
var instance1 = container.GetInstance<TestClass>();
instance1.GetDataByAccountNumber(1);
var instance2 = container.GetInstance<TestClass>();
instance2.GetDataByAccountNumber(2);
Assert.That(instance2.CallerId == 2);
}
The test class looks like this
public class TestClass
{
public int CallerId = 0;
[CacheableMethod(30)] // TODO - put to 20 minutes and have value in WebConfig as constant
public virtual List<MyResponse> GetDataByAccountNumber(int callerId)
{
CallerId = callerId;
var response = StubResponse();
return response;
}
// ...
Simply registering with a lifetime scope does not appear to be compatible with dynacache. In this test method the container returns the same instance for each call within the scope of the lifetime but the results of the method are not cached ....
[Test]
public void GetDataByAccountNumber_CalledTwiceLifetimeScopedInstance_ReturnsCacheSecondTime()
{
var container = new Container();
container.Register<IDynaCacheService>(() => new MemoryCacheService());
container.Register(typeof(TestClass), Cacheable.CreateType<TestClass>(), new LifetimeScopeLifestyle());
using (container.BeginLifetimeScope())
{
var instance1 = container.GetInstance<TestClass>();
instance1.GetDataByAccountNumber(1);
var instance2 = container.GetInstance<TestClass>();
instance2.GetDataByAccountNumber(2);
// the container does return the same instance
Assert.That(instance1, Is.EqualTo(instance2));
// but the caching does not work
Assert.That(instance2.CallerId, Is.EqualTo(1));
}
}
My advice is that you implement caching with decorators which is real easy with Simple Injector - read the articles of @Steven's starting here
回答2:
For registering with SimpleInjector it should be done as below:
container.RegisterSingle<IDynaCacheService>(new MemoryCacheService());
container.Register(typeof(ITestClass), Cacheable.CreateType<TestClass>());
Once I done this Caching worked as expected.
Updated with Full test sample Program
using System;
namespace DynaCacheSimpleInjector
{
using System.Threading;
using DynaCache;
using SimpleInjector;
class Program
{
static void Main()
{
var container = new Container();
container.RegisterSingle<IDynaCacheService>(new MemoryCacheService());
container.Register(typeof(ITestClass), Cacheable.CreateType<TestClass>());
var instance = container.GetInstance<ITestClass>();
for (var i = 0; i < 10; i++)
{
// Every 2 seconds the output will change
Console.WriteLine(instance.GetData(53));
Thread.Sleep(500);
}
}
}
public class TestClass : ITestClass
{
[CacheableMethod(2)]
public virtual string GetData(int id)
{
return String.Format("{0} - produced at {1}", id, DateTime.Now);
}
}
public interface ITestClass
{
string GetData(int id);
}
}
来源:https://stackoverflow.com/questions/24283202/dynacache-doesnt-cache-data