Created
May 29, 2013 23:47
-
-
Save oguzhaneren/5674735 to your computer and use it in GitHub Desktop.
Castle Interceptor Caching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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