I have a class that I use for the checking method arguments, which you call in the form:
public void SomeMethod(string anArg)
{
Ensure.ArgumentNotNull(() => anArg);
}
If the argument is null then an ArgumentNullException
with the name of the property is thrown. This is done like so:
public static void ArgumentNotNull<T>(Expression<Func<T>> expression) where T : class
{
var value = expression.Compile()();
if (value == null)
{
throw new ArgumentNullException(expression.GetMemberName());
}
}
Where GetMemberName
is an extension method I've written.
The problem I'm having is that the call to Compile is very slow, so I'd like to cache the result, but I don't seem to be able to come up with a cache key that will be unique enough to prevent cache conflicts, but not so unique that the cache becomes invalid.
My best effort so far is:
internal static class ExpressionCache<T>
{
private static readonly Dictionary<string, Func<T>> Cache = new Dictionary<string, Func<T>>();
public static Func<T> CachedCompile(Expression<Func<T>> targetSelector)
{
Func<T> cachedFunc;
var cacheKey = targetSelector + targetSelector.Body.ToString();
if (!Cache.TryGetValue(cacheKey, out cachedFunc))
{
cachedFunc = targetSelector.Compile();
Cache[cacheKey] = cachedFunc;
}
return cachedFunc;
}
}
But this still causes cache key conflicts. What might be a better approach?
Where do the exrpessions come from, are they created new? If they are reused, you could just use the expression itself as the key.:
internal static class ExpressionCache<T>
{
private static readonly Dictionary<Expression<Func<T>, Func<T>> Cache = new Dictionary<Expression<Func<T>, Func<T>>();
public static Func<T> CachedCompile(Expression<Func<T>> targetSelector)
{
Func<T> cachedFunc;
if (!Cache.TryGetValue(targetSelector, out cachedFunc))
{
cachedFunc = targetSelector.Compile();
Cache[targetSelector] = cachedFunc;
}
return cachedFunc;
}
}
Else you could snoop around int he source code for the DLR http://dlr.codeplex.com/, I believe they address this kind of questions quite well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With