I want to write a wrapper for the System.Web.Caching.Cache, which handles my cache requests.
I need a method, which can invoke a callback method, if the cache entry doesn't exist. The problem is: I dont know how many params the callback method has:
public T Get<T, TCallback>(string key, TCallback func) where TCallback : Func<T>
{
// check cachekey, do sth
T result = func.Invoke();
return result;
}
With this implementation it's possible to give a callback without params. But what if I have some?
Thanks,
trial
This method should only accept the parameters that this implementation wants to send to a given function. If it has no information that would be relevant to such a callback then it should simply require a parameter-less delegate. If it has parameters that will be needed for some, but won't be needed for others, it should provide them in all cases, using a single delegate.
It then becomes the responsibility of the caller to match the function that they want to call with the signature of the delegate. If they want to fix values for some function that has parameters your callback doesn't have, or if they want to call a function with less parameters, etc. it is their responsibility to make the "conversion", rather than this method's responsibility to deal with a delegate with an unknown signature.
The use of lambdas makes "converting" functions very easy; much easier than the alternative. To fix a value for a parameter when your callback doesn't have one, you can close over the variable:
int value = 5;
Get("key", () => SomeMethod(value));
You can also use a lambda to ignore a parameter:
Get("key", someParameterToIgnore => AnotherMethod());
1) You can use dynamic or Dictionary as parameter of your callback. Put in Dictionary or dynamic string value - like CallbackType.
Its bad because you lost static type analysing, but it possible.
2)It may be useful: Ellipsis notation in C#?
Related
For a test, I want to create a generic "helper" method which will take take two arguments, the first argument is a function (or a reference to the function) and the 2nd argument is a list of objects for that function that are to be called as its parameters.
The following does this perfectly:
CallMyFunctionWithParamsPlease(new Func<int, int>(MyMethod), new object[] {1});
public static int CallMyFunctionWithParamsPlease(Delegate func, params object[] args)
{
func.DynamicInvoke(args);
return 3;
}
The thing is, this doesn't look very nice when calling it and I wish to abstract it into another method to act as syntatic sugar.
Ideally I want it to be called like this:
CallMyFunctionWithParamsPlease(myMethod, new Object[] {1});
From what I can gather, there is no elegant solution to do this in C# since I cannot pass myMethod by itself as a reference anywhere, instead I must pass it by declaring a new Func along with the return type of the method. Since I'm not using this return type anywhere, I'm not sure why it's necessary to input this information. My limited understanding is that because C# is statically typed, the compiler must know everything and things like this just aren't possible.
Is this true or not? How would I create syntatic sugar to simply pass a method to another method which can be called there without needing to invoke "new Func"? I would have thought simply passing the function as a reference pointer would allow me to do this, but I'm having difficultly doing this too. I looked into delegates, using "unsafe" with pointers, and a few other options. None of them seem to make this possible, or if they do, they didn't explain it in a manner that I could understand.
I simply want to pass a method to another method, and invoke it with a variable list of object params with variable length whereby I don't need to specify this whilst invoking it. I'm not sure if I'm trying to force C# to do something it's not meant to do here, and instead I'd be better off using a dynamically typed language to do this. The problem is I really enjoy the intellisense that the static typing of C# offers, along with the performance improvements over a language like Python. I'd just like a way to syntactically abstract away the boilerplate with my own helper methods for things like this.
UPDATE: Thanks to the comments here it seems I can do this with a lambda expression nice and elegantly. The signature can be simply changed to public static long CallMyFunctionWithParamsPlease<T>(Func<T> func)
If deferred execution is what you want simply pass a Func<TReturnType> to your method (or class). The calling method doesn't need to know how many parameters are involved.
e.g. Assuming MyMethod has a signature int MyMethod(int arg):
CallMyFunctionWithParamsPlease(() => MyMethod(1));
public static int CallMyFunctionWithParamsPlease(Func<int> func)
{
return func();
}
If MyMethod takes two parameters, it's the same call:
CallMyFunctionWithParamsPlease(() => MyMethod(1, 2));
I've seen some C# methods, like ThreadPool.QueueUserWorkItem(WaitCallback, Object), that take a method ("WaitCallback" in this case) but instead of providing an option to directly pass arguments to the method, instead take a separate Object that can supply them.
So you can't do something like is being asked here.
My question is: Why?
There must be a technical reason to use this approach and not allow something like
ThreadPool.QueueUserWorkItem(new WaitCallback(Multiply(2, 3)));
private int Multiply(int x,int y)
{
int z=(x*y);
return z;
}
Because you want to pass a delegate to WaitCallBack. In simple words, you want to tell WaitCallBack the method the thread has to execute, but you don't want to call that method now.
In your example
ThreadPool.QueueUserWorkItem(new WaitCallback(Multiply(2, 3)));
the method Multiply would be called directly and its result should be passed to the WaitCallback constructor (which isn't possible).
There is no way for the compiler to decide if you wanted to call Multiply here or just want to tell WaitCallback that is has to do that call, because it would be totally the same syntax.
Thatswhy you tell it which method method it should call and - separatly - which argument it should pass when it eventually calls it.
But you could use a lambda instead:
ThreadPool.QueueUserWorkItem(o => Multiply(2, 3));
Now the thread can execute this lambda, which in turn calls Multiply(2, 3) (discarding the argument o).
I have a method that accepts an Action with a signature like:
public void DoSomething(Action code);
then I would call this method like:
DoSomething(()=> CallSomething("A","B","C");
In the DoSomething method, how can I get the argument values?
Another thing to consider is that CallSomething can potentially have optional parameters, meaning I can't just change the signature of DoSomething to -> Expression<Action>
All I need to do is get the argument values, I'm interested in any method that can work.
I've already tried to create a new method which accepts Expression<Action> then pass the Action through (From DoSomething), but the arguments weren't populated.
Any suggestions welcome.
The point is you don't want to.
Your method accepts an Action delegate. It's saying "I only want something to call that has no arguments and returns no value".
If you need to pass arguments to the function, either use a different delegate, or pass them as arguments directly.
Think about this without the lambda. You have an interface that has a single method, Act that takes no arguments and returns no value.
DoSomething(IMyInterface myInterface)
{
myInterface.Act(); // How do I get the arguments of some method that `Act` calls?
}
Does this make any sense whatsoever? Would you expect to be able to disassemble the whole instance that's passed in myInterface, find its Act method, go through all of the methods that are called from there and intercept their arguments? Delegates are little but a single-method interface with a bit of state carried over.
If you need the arguments, make them part of the public interface. Otherwise, your abstraction has no meaning whatsoever, and you shouldn't be using it. Nobody is forcing you to use lambdas, and nobody is forcing you to pass a single lambda and no arguments, and nobody is forcing you to use Action in particular. They are all simple tools - if they don't fit your task, don't use them.
To answer your question more directly: you get the arguments as any other arguments. The problem is that your action has no arguments.
I want to implement a method that will find stuff in my custom class. It should work like generic collections work - i pass a pointer to a function, and the method will iterate through all it has to look in, apply this function, and if it returns true return the found item.
I'd like to pass function pointer as a parameter, but i dont want to declare delegate types.
I know i can do something like:
delegate bool Foo(MyClass)
MyClass MyMethod(Foo x)
{...}
And i know i can do something like this:
MyClass MyMethod(Func<MyClass,bool> x)
But can i do it without declaring a delegate type and without using built in stuff like Func<> which has limits on how many parameters i can have (in case of Func, one...)
You can just use delegate if you want, although it's a bit old school :)
public void TestInvokeDelegate()
{
InvokeDelegate( new TestDelegate(ShowMessage), "hello" );
}
public void InvokeDelegate(TestDelegate del, string message)
{
del(message);
}
public delegate void TestDelegate(string message);
public void ShowMessage(string message)
{
Debug.WriteLine(message);
}
You can allways pass in a Delegate and call DynamicInvoke on it:
MyClass MyMethod(Delegate x) {
// ...
x.DynamicInvoke(....);
// ...
}
It looks like you are trying to implement the Visitor pattern. In this case visiting methods usually have only one parameter - the instance to visit. Having additional arguments passed around conceals the use of the pattern and makes it harder to reason about. This article shows you one way to implement it in C#.
The key is to create a visitor class that will encapsulate all the parameters that affect the visiting process. This way you don't need to pass anythnig other than an object in question in the visiting method - everything else lives in instance fields.
However, if you really want to pass some additional parameters in the method and don't know what type they can have, there are ways to do that. More or less standard approach in .NET world is to use a delegate without return value and with single parameter of type object, the example would be ParameterizedThreadStart delegate:
public delegate void ParameterizedThreadStart(
Object obj
)
This way you get to pass only one parameter in the delegate, but it could be anything - an instance of a class, an array or null, if you end up not needing additional arguments after all. The downside of this approach is that it requires type casting which can lead to runtime errors.
I'm coding a .NET library in C# for communicating with XBMC via its JSON RPC interface using HTTP.
I coded and released a preliminary version but everything is done synchronously. I then recoded the library to be asynchronous for my own purposes as I was/am building an XBMC remote for WP7.
I now want to release the new async library but want to make sure it's nice and tidy before I do.
Due to the async nature a user initiates a request, supplies a callback method that matches my delegate and then handles the response once it's been received.
The problem I have is that within the library I track a RequestState object for the lifetime of the request, it contains the http request/response as well as the user callback etc. as member variables, this would be fine if only one type of object was coming back but depending on what the user calls they may be returned a list of songs or a list of movies etc.
My implementation at the moment uses a single delegate ResponseDataRecieved which has a single parameter which is a simple Object - As this has only be used by me I know which methods return what and when I handle the response I cast said object to the type I know it really is - List, List etc.
A third party shouldn't have to do this though - The delegate signature should contain the correct type of object. So then I need a delegate for every type of response data that can be returned to the third party - The specific problem is, how do I handle this gracefully internally - Do I have a bunch of different RequestState objects that each have a different member variable for the different delegates? That doesn't "feel" right. I just don't know how to do this gracefully and cleanly.
If I understood you correctly, you have an interface that provides multiple methods, each of which takes basically the same kind of delegate, but gets a different type of parameter as input. Something like this:
GetListOfSongs(..., delegate(List<Song> result) { ... });
GetListOfMovies(..., delegate(List<Movie> result) { ... });
and you're worried about the delegate signatures that start cropping up along with the methods in the interface?
If that's the case, then generics are what you're looking for. In fact, if your delegate signature matches my example -- that is, accepts one input parameter, returns no value -- the delegate type you want already exists in the BCL. It's called Action<T>. You could declare the methods above like so:
GetListOfSongs(..., Action<List<Song>> callback);
GetListOfMovies(..., Action<List<Movie>> callback);
and you'd still only have a single delegate type, that is, Action<T>.
Now, if you need to pass along more than one parameter, you're still covered. There exist versions of Action for up to 16 input parameters (although their signatures begin to look a bit garish: Action<T1, T2, T3 ...>).
If you want your callback to also return a value that you'll use somewhere within your infrastructure, Func<T, TResult> is your friend (T is the type of the input parameter, TResult is the type of the value you will return from the delegate).
As a bonus, I'd recommend you don't expose List<T> in your interfaces. If you really think all your clients will need list operations, use IList<T>, but consider ICollection<T> or even IEnumerable<T> if they won't.
The first thing that comes to mind is generics: ResponseDataRecieved<T> where T is the type expected in the callback. However, you could save the callbacks as captured variables. For example:
public delegate void CallBackA(int i);
public delegate void CallBackB(string s);
public class RequestHandler
{
public void QueueRequestA(CallBackA callback)
{
Task.Factory.StartNew(() =>
{
int ret = 0;
//ret = get stuff of type A from server
callback(ret); //callback is captured here
});
}
public void QueueRequestB(CallBackB callback)
{
Task.Factory.StartNew(() =>
{
string str = "";
//str = get stuff of typw B from server
callback(str); //callback is captured here
});
}
}