I have a need to pass a delegate method with a varying number and type of parameters to another method. My hope is to be able to inspect the values of the parameters within the call.
This is my generic cache class.
public T Get<T>(Expression<Func<T>> getItemCallback) where T : class
{
T item = HttpRuntime.Cache.Get(hashRepresentationOfValues) as T;
if (item == null)
{
item = getItemCallback.Compile()();
HttpRuntime.Cache.Insert(
hashRepresentationOfValues,
item,
null,
DateTime.Now.AddMinutes(5),
TimeSpan.Zero);
}
return item;
}
My calls look like the following:
private DataContext db;
return cache.Get<List<SomeDBObject>>(
() => db.SomeDBObjectCall(param1, param2, param3));
As you can see it would be extremely helpful if I could dynamically determine the values of the delegate call as they could be used as the cache-key.
So basically, you have a method with an unknown signature that you want to wrap for caching purposes. If that's the case, you will definitely want to look into a technique called Memoization
Memoization on Wikipedia
In computing, memoization is an optimization technique used primarily to speed up computer programs by having function calls avoid repeating the calculation of results for previously processed inputs.
An example of such a function in C# would be something along these lines:
static Func<A, R> Memoize(this Func<A, R> f)
{
var dict = new Dictionary<A, R>();
return (A arg)=>
{
R result;
if (!dict.TryGetValue(arg, out result))
{
result = f(arg);
dict.Add(arg, result);
}
return result;
};
}
Note that the method takes a generic Func and returns a generic Func with the same signature. This way, you can effectively wrap your methods without bogging up the rest of your code. It is really seamless!
More examples here and here
Related
I have a dictionary where the key is a string and the value is an Action. I setup mapping of string keys to functions. I then have a list that I call .ForEach() on and inside this I use a value in the list as the key and then call the function associated with it. The issue will come if the key doesn't exist. How can I check this in the .ForEach function? I'd like to use the ternary operator but it doesn't seem to work.
private Dictionary<string, Func<IniConfig, object>> typeMapping = new Dictionary<string, Func<IniConfig, object>>();
typeMapping["MB"] = ProcessMB;
public object ProcessMB(IniConfig file)
{
return null;
}
object iif(bool expression, object truePart, object falsePart)
{ return expression ? truePart : falsePart; }
FilesToProcess.ForEach(x => iif(typeMapping.ContainsKey(x.ExtractType), typeMapping[x.ExtractType](x), Error(x)));
This highlights the 2nd parameter in the iif() call with error: Argument 2: cannot convert from 'void' to 'object', and the same thing for the Error(x) part.
So it seems like the ternary operator returns an object? So if I change my Action to a Func and have the return type be object and make my functions return object it compiles, but when I run a test with an invalid key it doesn't go into my Error() function it throws "The given key was not present in the dictionary" exception. I would expect it to do the ternary operation and see that typeMapping doesn't have the key and so fail to the Error() function. What am I missing?
Your iif() method is counter-intuitive here, and it seems like an over-use of LINQ. Here is what I would do:
foreach (var file in filesToProcess)
{
Func<IniConfig, object> action;
if (typeMapping.TryGetValue(file.ExtractType, out action))
{
action(file);
}
else
{
Error(file);
}
}
Makes your code easier to read too :)
Edit:
I Have found a generic way to do what you want. First you need to create an extension method for IDictionary<TKey,TVal> that simply returns the default value if a key does not exist:
public static TVal GetValueOrDefault<TKey, TVal>(this IDictionary<TKey, TVal> self, TKey key)
{
TVal ret;
self.TryGetValue(key, out ret);
return ret;
}
Then you can use the null coalescing (??) operator:
FilesToProcess.ForEach((typeMapping.GetValueOrDefault(x.ExtractType) ?? Error)(x));
Make your life easy and just create a little helper function that does what you want:
private void InvokeProcessor(IniConfig iniConfig)
{
Func<IniConfig, object> processor;
if (typeMapping.TryGetValue(x.ExtractType, out processor)
processor(iniConfig);
else
Error(iniConfig);
}
Then use it like so:
FilesToProcess.ForEach(InvokeProcessor);
Easy to read and understand. Also faster because the dictionary will only be searched once for each file.
Edit
Alright, if you really wanna use that weird iif() thing, here's how to fix it:
object iif(bool expression, Func<object> truePart, Func<object> falsePart)
{ return expression ? truePart() : falsePart(); }
...and how to use it:
FilesToProcess.ForEach(x => iif(
typeMapping.ContainsKey(x.ExtractType),
() => typeMapping[x.ExtractType](x),
() => Error(x)));
Basically the evaluation of the 2nd and 3rd argument of iif() is delayed until one of them is actually needed. In your previous version all arguments were evaluated before the execution of iff() resulting in a call to the dictionary indexer and to Error() every time a IniConfig object was processed.
A word of warning though: if you use this in production then harakiri might be your only way out of the devastating shame that will overcome you a couple years later.
UPDATED:
I am trying to write a method to do somes work and before it actually does those works it needs to go through some validations. Those validation varies based on what work it's going to do.
After some thoughts, I still want to use the same patterns with some minor changes.
Now, I want to make the following code works:
SomeClass:
public SomeResponse DoSomething<T>(params Func<T, bool>[] validations)
{
if(validations.All(v=>v(T))
{
some logic..
}
return SomeResponse;
}
Usage:
private Func<SomeRequest, bool> ValidateName = r =>
{return !string.IsNullOrWhiteSpace(r.Name);};
private Func<SomeRequest, bool> ValidatePhone = r =>
{return !string.IsNullOrWhiteSpace(r.Phone);};
var someResponse = SomeClass.DoSomething<SomeRequest>(ValidateName,ValidatePhone);
Again, the code currently doesn't work because it's giving me error on
if(validations.All(v=>v(T))
basically Type parameter is not valid here, and I couldn't find a way to pass in an actual SomeRequest object to the Func.
How should I write the code to loop through all the results return by the list of functions and make sure they are returning true, as well as keeping the flexibility of the Type parameter?
Answer:
Found a way to do that, hope this can be helpful:
Simply modify the method definition to :
SomeClass:
public SomeResponse DoSomething<T>(T request, params Func<T, bool>[] validations)
{
if(validations.All(v=>v(request))
{
some logic..
}
return SomeResponse;
}
Then use it like:
var someResponse = SomeClass.DoSomething<SomeRequest>(someRequest, ValidateName,ValidatePhone);
Please let me know if there is any other solution.
You're almost there!
First note that Validations is an array of Func<Request, bool> - that is, each item in the array is a function which takes a Request as a parameter and returns a bool.
So in order to get the bool out of the Func, you need to apply it to a Request object. In C#, applying a Func to an argument looks just like calling a method. So your LINQ expression will look like this:
validations.All(f => f(request))
This will return true if and only if all of the functions in validations return true (when applied to request).
So your full if block will look like this:
// I'm just guessing what the code to make a Request object will look like
Request request = resource.GetRequest();
if (!validations.All(f => f(request)))
{
throw new Exception("Not all of the validations checked out");
}
You haven't provided enough context for me to tell you where to get a Request object from but I'm sure you can figure it out.
Assuming I'm understanding these types correctly, I would think something like this should work:
if (Validations.All(v => v(resource)))
You don't need to use params here, a simple array will do. You can pass an arbitrary number of Func objects with an array.
public void DoSomething(Resource resource, Func<Request, bool>[] Validations)
Anyway, you can easily use LINQ's All method to check if all elements of an array satisfy a predicate.
if (Validations.All(v => v(resource)))
For example, consider a utility class SerializableList:
public class SerializableList : List<ISerializable>
{
public T Add<T>(T item) where T : ISerializable
{
base.Add(item);
return item;
}
public T Add<T>(Func<T> factory) where T : ISerializable
{
var item = factory();
base.Add(item);
return item;
}
}
Usually I'd use it like this:
var serializableList = new SerializableList();
var item1 = serializableList.Add(new Class1());
var item2 = serializableList.Add(new Class2());
I could also have used it via factoring, like this:
var serializableList = new SerializableList();
var item1 = serializableList.Add(() => new Class1());
var item2 = serializableList.Add(() => new Class2());
The second approach appears to be a preferred usage pattern, as I've been lately noticing on SO. Is it really so (and why, if yes) or is it just a matter of taste?
Given your example, the factory method is silly. Unless the callee requires the ability to control the point of instantiation, instantiate multiple instances, or lazy evaluation, it's just useless overhead.
The compiler will not be able to optimize out delegate creation.
To reference the examples of using the factory syntax that you gave in comments on the question. Both examples are trying (albeit poorly) to provide guaranteed cleanup of the instances.
If you consider a using statement:
using (var x = new Something()) { }
The naive implementation would be:
var x = new Something();
try
{
}
finally
{
if ((x != null) && (x is IDisposable))
((IDisposable)x).Dispose();
}
The problem with this code is that it is possible for an exception to occur after the assignment of x, but before the try block is entered. If this happens, x will not be properly disposed, because the finally block will not execute. To deal with this, the code for a using statement will actually be something more like:
Something x = null;
try
{
x = new Something();
}
finally
{
if ((x != null) && (x is IDisposable))
((IDisposable)x).Dispose();
}
Both of the examples that you reference using factory parameters are attempting to deal with this same issue. Passing a factory allows for the instance to be instantiated within the guarded block. Passing the instance directly allows for the possibility of something to go wrong along the way and not have Dispose() called.
In those cases, passing the factory parameter makes sense.
Caching
In the example you have provided it does not make sense as others have pointed out. Instead I will give you another example,
public class MyClass{
public MyClass(string file){
// load a huge file
// do lots of computing...
// then store results...
}
}
private ConcurrentDictionary<string,MyClass> Cache = new ....
public MyClass GetCachedItem(string key){
return Cache.GetOrAdd(key, k => new MyClass(key));
}
In above example, let's say we are loading a big file and we are calculating something and we are interested in end result of that calculation. To speedup my access, when I try to load files through Cache, Cache will return me cached entry if it has it, only when cache does not find the item, it will call the Factory method, and create new instance of MyClass.
So you are reading files many times, but you are only creating instance of class that holds data just once. This pattern is only useful for caching purpose.
But if you are not caching, and every iteration requires to call new operator, then it makes no sense to use factory pattern at all.
Alternate Error Object or Error Logging
For some reason, if creation fails, List can create an error object, for example,
T defaultObject = ....
public T Add<T>(Func<T> factory) where T : ISerializable
{
T item;
try{
item = factory();
}catch(ex){
Log(ex);
item = defaultObject;
}
base.Add(item);
return item;
}
In this example, you can monitor factory if it generates an exception while creating new object, and when that happens, you Log the error, and return something else and keep some default value in list. I don't know what will be practical use of this, but Error Logging sounds better candidate here.
No, there's no general preference of passing the factory instead of the value. However, in very particular situations, you will prefer to pass the factory method instead of the value.
Think about it:
What's the difference between passing the parameter as a value, or
passing it as a factory method (e.g. using Func<T>)?
Answer is simple: order of execution.
In the first case, you need to pass the value, so you must obtain it before calling the target method.
In the second case, you can postpone the value creation/calculation/obtaining till it's needed by the target method.
Why would you want to postpone the value creation/calculation/obtaining? obvious things come to mind:
Processor-intensive or memory-intensive creation of the value, that you want to happen only in case the value is really needed (on-demand). This is Lazy loading then.
If the value creation depends on parameters that are accessible by the target method but not from outside of it. So, you would pass Func<T, T> instead of Func<T>.
The question compares methods with different purposes. The second one should be named CreateAndAdd<T>(Func<T> factory).
So depending what functionality is required, should be used one or another method.
i have 5 datafunctions which all return the same type of object (List<source>)
Now i have to publish them in a WCF in which i have to surround the called code with all kind of error handling code (about 50 lines).
So i thought: because the code (51 lines) is all the same except the one line to get the data, just create one function with all the errorhandling a pass the function to get the data as a parameter to that function.
So i have these functions:
GetAllSources() : List<Source>
GetAllSourcesByTaskId(int taskId) : List<Source>
GetAllSourcesByTaskIdPersonId(int taskId, int personId) : List<Source>
GetAllSourcesByDate(DateTime startDate, DateTime endDate): List<Source>
and i want be able to pass them as a parameter to a function.
How should i declare the called function?
ps
i've read this one
how to pass any method as a parameter for another function
but it uses an Action object which can't return anything (as far as i understand) and i want to return a List
This should work:
List<Source> WithErrorHandling(Func<List<Source>> func)
{
...
var ret = func();
...
return ret;
}
Usage:
var taskId = 123;
var res = WithErrorHandling(() => { GetAllSourcesByTaskId(taskId); });
You can pass a Func which can take many input parameters are return a value:
Func<T1, T2, TResult>
In your case something like this could work:
public List<Source> GetList(Func<List<Source>> getListMethod) {
return getListMethod();
}
Then call using
GetList(() => GetAllSources());
GetList(() => GetAllSourcesByTaskIdPersonId(taskId, personId));
Could you not just pass the List as an argument into your method, might be a bit tidier?
Well, you didn't say anything about the code inside these functions, but if you use linq inside, than your approach is definitely not the best one.
You should use something like this:
IQueriable<SomeType> GetAllSources()
{
return (from source in sources select ...);
}
IQueriable<SomeType> GetAllSourcesByTaskId(int taskId)
{
return (GetAllSources()).Where(source => source.TaskId == taskId);
}
I am trying to develop an NUnit addin that dynamically adds test methods to a suite from an object that contains a list of Action delegates. The problem is that NUnit appears to be leaning heavily on reflection to get the job done. Consequently, it looks like there's no simple way to add my Actions directly to the suite.
I must, instead, add MethodInfo objects. This would normally work, but the Action delegates are anonymous, so I would have to build the types and methods to accomplish this. I need to find an easier way to do this, without resorting to using Emit. Does anyone know how to easily create MethodInfo instances from Action delegates?
Have you tried Action's Method property? I mean something like:
MethodInfo GetMI(Action a)
{
return a.Method;
}
You don't need to "create" a MethodInfo, you can just retrieve it from the delegate :
Action action = () => Console.WriteLine("Hello world !");
MethodInfo method = action.Method
MethodInvoker CvtActionToMI(Action d)
{
MethodInvoker converted = delegate { d(); };
return converted;
}
Sorry, not what you wanted.
Note that all delegates are multicast, so there isn't guaranteed to be a unique MethodInfo. This will get you all of them:
MethodInfo[] CvtActionToMIArray(Action d)
{
if (d == null) return new MethodInfo[0];
Delegate[] targets = d.GetInvocationList();
MethodInfo[] converted = new MethodInfo[targets.Length];
for( int i = 0; i < targets.Length; ++i ) converted[i] = targets[i].Method;
return converted;
}
You're losing the information about the target objects though (uncurrying the delegate), so I don't expect NUnit to be able to successfully call anything afterwards.