Reputation: 5541
I would like to create a few overloaded methods which accept a Func parameter. The overloaded methods should call the method with the most generic types defined in the parameter. Below is a quick example of my methods, and how I would like to call them:
public static TResult PerformCaching<TResult, T1>(Func<T1, TResult> func, T1 first, string cacheKey)
{
return PerformCaching((t, _, _) => func, first, null, null, cacheKey);
}
public static TResult PerformCaching<TResult, T1, T2>(Func<T1, T2, TResult> func, T1 first, T2 second, string cacheKey)
{
return PerformCaching((t, t2, _) => func, first, second, null, cacheKey);
}
public static TResult PerformCaching<TResult, T1, T2, T3>(Func<T1, T2, T3, TResult> func, T1 first, T2 second, T3 third, string cacheKey)
{
Model data = Get(cacheKey);
if(data == null)
{
Add(cacheKey);
data = func.Invoke(first, second, third);
Update(data);
}
return data;
}
Would it be possible to get it working like this? Another question is what is happening to the func, when it reaches the final method. Would it execute it with one parameter (when the first method is called) or is it called with all three parameters.
Upvotes: 5
Views: 1532
Reputation: 10547
You have to project from Func<T, T1, T2>
to Func<T, T1, T2, T3>
. It's not hard but I'm not sure this is the best approach. You also have other generic issues, like casting to Model (which I converted to string). A better approach would likely be something like Cache.Retrieve<TResult>(string cashKey, Func<TResult> missingItemFactory)
. Then you would call like Cache.Retrieve("model1", () => repository.Get<Model>(myId))
then just call if (data == null) data = missingItemFactory();
inside your method.
Regardless, a solution is below.
void Main()
{
Func<string, string> f1 = s => "One";
Func<string, string, string> f2 = (s1, s2) => "Two";
Func<string, string, string, string> f3 = (s1, s2, s3) => "Three";
Console.WriteLine(PerformCaching(f1, "one", "f1"));
Console.WriteLine(PerformCaching(f1, "one", "f1"));
Console.WriteLine(PerformCaching(f2, "one", "two", "f2"));
Console.WriteLine(PerformCaching(f2, "one", "two", "f2"));
Console.WriteLine(PerformCaching(f3, "one", "two", "three", "f3"));
Console.WriteLine(PerformCaching(f3, "one", "two", "three", "f3"));
}
// Define other methods and classes here
public static TResult PerformCaching<TResult, T1>(Func<T1, TResult> func, T1 first, string cacheKey)
{
return PerformCaching<TResult, T1, string, string>((t, t2, t3) => func(t), first, null, null, cacheKey);
}
public static TResult PerformCaching<TResult, T1, T2>(Func<T1, T2, TResult> func, T1 first, T2 second, string cacheKey)
{
return PerformCaching<TResult, T1, T2, string>((t, t2, t3) => func(t, t2), first, second, null, cacheKey);
}
public static TResult PerformCaching<TResult, T1, T2, T3>(Func<T1, T2, T3, TResult> func, T1 first, T2 second, T3 third, string cacheKey)
{
TResult data = Get<TResult>(cacheKey);
if(data == null)
{
Add(cacheKey);
data = func.Invoke(first, second, third);
Update(data);
}
return data;
}
public static T Get<T>(string CashKey) { return default(T); }
public static void Add(string CashKey) { }
public static void Update<T>(T data) { }
Upvotes: 0
Reputation: 1500465
No, that approach wouldn't work. You'd be trying to pass a Func<T1, TResult>
to a method accepting a Func<T1, T2, T3, TResult>
- and that simply doesn't work. I would suggest changing to something like this:
public static TResult PerformCaching<TResult>(Func<TResult> func,
string cacheKey)
{
// Do real stuff in here
// You may find ConcurrentDictionary helpful...
}
public static TResult PerformCaching<T1, TResult>
(Func<T1, TResult> func, T1 first, string cacheKey)
{
return PerformCaching(() => func(first), cacheKey);
}
public static TResult PerformCaching<T1, T2, TResult>
(Func<T1, T2, TResult> func, T1 first, T2 second, string cacheKey)
{
return PerformCaching(() => func(first, second), cacheKey);
}
public static TResult PerformCaching<T1, T2, T3, TResult>
(Func<T1, T2, T3, TResult> func, T1 first, T2 second, T3 third,
string cacheKey)
{
return PerformCaching(() => func(first, second, third), cacheKey);
}
Upvotes: 8