Note that there are some explanatory texts on larger screens.

plurals
  1. POUniquely identifying anonymous method with parameters of Func body
    primarykey
    data
    text
    <p>I'm trying to write some magic code for handling caching that may or may not be possible. Basically, the idea is to have a CacheManager class with a static method which accepts an Func to execute as a parameter. In the static method's body, it would be able to execute that Func and cache the results using a cache key that uniquely identifies the internals of that Func passed (an anonymous method with 0 or more parameters). Subsequent calls to that static method with the same arguments provided would result in the same cache key and return the cached results.</p> <p>I need a way of uniquely identifying the anonymous function that is passed in.</p> <p><em><strong>Edit:</strong> Expression provided the answer once I adjusted the anonymous function syntax.</em> </p> <p>I'm worried about the performance impact of having to compile the expression at run-time. Given this is an attempt to support caching for performance it'd be silly for the compile to take any significant amount of time. Any thoughts? </p> <p><strong>Basic repository for testing:</strong></p> <pre><code>public class Product { public int ID { get; set; } public string Name { get; set; } } public class ProductRepository { private List&lt;Product&gt; products { get; set; } public ProductRepository() { products = new List&lt;Product&gt;() { new Product() { ID = 1, Name = "Blue Lightsaber" }, new Product() { ID = 2, Name = "Green Lightsaber" }, new Product() { ID = 3, Name = "Red Lightsaber" } }; } public Product GetByID(int productID) { return products.SingleOrDefault(p =&gt; p.ID == productID); } } </code></pre> <p><strong>CacheManager:</strong></p> <pre><code>public class CacheManager { public static TResult Get&lt;TResult&gt;(Expression&lt;Func&lt;TResult&gt;&gt; factory) { if (factory == null) throw new ArgumentNullException("factory"); var methodCallExpression = factory.Body as MethodCallExpression; if (methodCallExpression == null) throw new ArgumentException("factory must contain a single MethodCallExpression."); string cacheKey = "|Repository:" + methodCallExpression.Method.DeclaringType.FullName + "|Method:" + methodCallExpression.Method.Name + "|Args"; foreach (var arg in methodCallExpression.Arguments) { cacheKey += ":" + (arg is ConstantExpression ? ((ConstantExpression)arg).Value : Expression.Lambda(arg).Compile().DynamicInvoke()); } if (HttpContext.Current.Cache[cacheKey] == null) { HttpContext.Current.Cache[cacheKey] = factory.Compile().Invoke(); } return (TResult)HttpContext.Current.Cache[cacheKey]; } } </code></pre> <p><strong>Usage:</strong></p> <pre><code>ProductRepository productRepository = new ProductRepository(); int productID = 1; Product product; // From repo product = CacheManager.Get&lt;Product&gt;(() =&gt; productRepository.GetByID(1)); // From cache product = CacheManager.Get&lt;Product&gt;(() =&gt; productRepository.GetByID(productID)); </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload