Skip to content

Instantly share code, notes, and snippets.

@oguzhaneren
Created May 29, 2013 23:47
Show Gist options
  • Save oguzhaneren/5674735 to your computer and use it in GitHub Desktop.
Save oguzhaneren/5674735 to your computer and use it in GitHub Desktop.
Castle Interceptor Caching
class Program
{
static void Main(string[] args)
{
new Program().Run(args);
}
private WindsorContainer _container;
public void Run(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
var worker = generator.CreateInterfaceProxyWithTarget(typeof (IWorker), new Worker(), new CacheInterceptor()) as IWorker;
Random rnd = new Random();
for (int i = 0; i < 100; i++)
{
Console.WriteLine(worker.Work(rnd.Next(0, 10)));
}
}
}
public interface IWorker
{
int Id { get; set; }
void WriteToScreen(string s);
double Work(int x);
}
public class Worker
: IWorker
{
public int Id { get; set; }
public void WriteToScreen(string s)
{
Console.WriteLine(s);
}
[Cache(CacheTypes.CacheForSameParameters)]
public double Work(int x)
{
Random rnd = new Random();
Console.Write("calculating...");
return x ;
}
}
public class CacheInterceptor
: IInterceptor
{
private readonly IDictionary<string, object> _cacheRepository;
public CacheInterceptor(IDictionary<string, object> cacheRepository)
{
_cacheRepository = cacheRepository;
}
public CacheInterceptor()
: this(new Dictionary<string, object>())
{
}
public void Intercept(IInvocation invocation)
{
var cacheAttribute = invocation.MethodInvocationTarget.GetCustomAttributes(typeof(CacheAttribute), false).OfType<CacheAttribute>().FirstOrDefault();
if (cacheAttribute == null)
invocation.Proceed();
else
{
var args = GetArgumentInfos(invocation);
var fullMethodHash = GetHashForCacheType(invocation, args, cacheAttribute);
object result;
if (_cacheRepository.TryGetValue(fullMethodHash, out result))
{
invocation.ReturnValue = result;
}
else
{
invocation.Proceed();
result = invocation.ReturnValue;
_cacheRepository.Add(fullMethodHash, result);
}
}
}
private static string GetHashForCacheType(IInvocation invocation, ArgumentInfo[] args, CacheAttribute cacheAttribute)
{
string argsHash = string.Empty;
if (cacheAttribute.CacheType == CacheTypes.CacheForSameParameters)
argsHash = string.Join("|", args.Select(a => string.Format("{0}:{1}", a.Argument.Name, a.Value)));
else if (cacheAttribute.CacheType == CacheTypes.CacheAfterFirstUsage)
argsHash = String.Empty;
string fullMethodHash = string.Format("Method=[{0}] Parameters=[{1}]", invocation.MethodInvocationTarget.Name, argsHash);
return fullMethodHash;
}
private ArgumentInfo[] GetArgumentInfos(IInvocation invocation)
{
ArgumentInfo[] args = null;
//string methodHash = string.Format("Method=[{0}]", invocation.MethodInvocationTarget.Name);
//if (!_arguments.TryGetValue(methodHash, out args))
//{
args = invocation.MethodInvocationTarget.GetParameters()
.Zip(invocation.Arguments, (p, v) => new ArgumentInfo
{
Argument = p,
Value = v
}).ToArray();
//_arguments.Add(methodHash, args);
//}
return args;
}
}
public struct ArgumentInfo
{
public ParameterInfo Argument { get; set; }
public object Value { get; set; }
}
public enum CacheTypes
{
CacheForSameParameters,
CacheAfterFirstUsage
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false)]
public class CacheAttribute
: Attribute, IInterceptorAttribute
{
public CacheTypes CacheType { get; set; }
public CacheAttribute(CacheTypes cacheType)
{
CacheType = cacheType;
}
}
public interface IInterceptorAttribute
{
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment