Dynamically create fallback delegate at runtime - c#

I'm trying to setup C# code to automatically create dummy or fallback delegates for methods that get called by an IronPython script and that are not explicitly implemtented, yet.
Say there's a script that calls the non-static C# class method "MoveTo" which isn't implemented in the corresponding class yet. Usually, in case it exists, it is added to the script's scope by creating a corresponding delegate instance that is given to the scope by a call to "SetVariable" with the name of the Method and the delegate instance. That works fine for methods that already are implemented.
In case the method is not yet implemented the call shall not fail but instead be redirected to a dummy method that gracefully handles the call and pretends successful execution (which is to be considered uncritical in my specific case).
The problem is: the methods invoked by the IronPython script have a wide range of signatures (actually they can have any possible kind of signature). Therefore I'd like to dynamically create a fallback delegate that gets the same signature of the called method and hence "catches" every call to not yet implemented methods.
Do you guys have any idea on how I can achieve this goal?

You should be able to create a catch-all method that takes any number/type of args:
object Fallback([ParamDictionary]IDictionary<object, object> kwargs, params object[] args) {
return null; // or whatever
}
(Sadly, this is backwards from the normal Python way of writing a similar function: def foo(*args, **kwargs):.)
If you don't use keywords args, you can drop that and just use params:
object Fallback(params object[] args) {
return null; // or whatever
}
Then use .SetVariable("whatever", Fallback) to make it the fallback method.

Related

Is it possible to simply pass a generic method with generic parameters as an argument to another method in C#?

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));

How to get the arguments from an Action?

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.

Generic Callbacks in C#

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#?

Can C# Delegates work this way?

I'm trying to use delegates to cut down on my code in this project.
I have 4 DropDownLists in my asp.net page. In my codebehind file I'm binding them to different business object calls with data. Right now I have the following code:
DeptList.DataSource = bl.getAcademicDepts();
DeptList.DataBind();
TermList.DataSource = bl.getTerms();
TermList.DataBind();
InstructorList.DataSource = bl.getInstructors();
InstructorList.DataBind();
EEList.DataSource = bl.getEE();
EEList.DataBind();
This seems really repetitive so I decided to make a function as a shortcut
private void SourceAndBind(DropDownList d, <business layer method call>)
{
d.DataSource = <businesslayer method call>();
d.DataBind();
}
Then my first block of code simply becomes
SourceAndBind(DeptList, bl.getAcademicDepts());
SourceAndBind(TermList, bl.getTerms());
SourceAndBind(InstructorList, bl.getInstructors());
SourceAndBind(EEList, bl.getEE());
However, I don't know what to put for the second parameter. Each one of the business layer calls takes no parameters, but they each return objects of different types. I tried using delegates but I couldn't figure out how to create one without a defined return type or no parameters. Is it possible to achieve what I want with c#? I know that works in python which is where I'm coming from.
You don't need delegates to do this. Just declare the second parameter as object.
// Takes drop down list and data to assign to 'data source'
private void SourceAndBind(DropDownList d, object data) {
d.DataSource = data;
d.DataBind();
}
// Call methods from bussiness layer and bind results
SourceAndBind(DeptList, bl.getAcademicDepts());
SourceAndBind(TermList, bl.getTerms());
SourceAndBind(InstructorList, bl.getInstructors());
SourceAndBind(EEList, bl.getEE());
You could use delegates too. However, since you're only calling the method once, you can call the bussiness layer method to get the data and then pass the result to SourceAndBind. (Delegates would be useful for example if you wanted to choose one of several ways of loading the data, or if you wanted to delay loading until some later point).
Well, Func<object> would be a very general way of doing that. That's "a function with no parameters that returns an object". Any parameterless function returning a reference type should be convertible to that delegate type. However, your "usage" code wouldn't be quite right as it. It would be:
SourceAndBind(DeptList, bl.getAcademicDepts);
SourceAndBind(TermList, bl.getTerms);
SourceAndBind(InstructorList, bl.getInstructors);
SourceAndBind(EEList, bl.getEE);
Note the lack of brackets, which means these are method groups rather than method calls. (To follow .NET naming conventions I'd suggest renaming your methods to start with capital letters, btw.)
That's appropriate if you only want to call the method conditionally. As Tomas says though, you don't need to use delegates here. If you're happy for SourceAndBind to only get called after you've called the method, you can definitely just perform the method call in the argument and pass the result as object.
private void SourceAndBind(DropDownList d, Func<IEnumerable<object>> businessLayerMethod)
{
d.DataSource = businessLayerMethod();
d.DataBind();
}
IEnumerable<object> where object is your datatype.

Running a dynamic void from a assembly loaded into an interface

So, i have an assembly that i loaded into the interface, and it works perfectly:
MarshalByRefObject pluginObject = ...
ecko.Plugins.Interface.Plugin plug = pluginObject as ecko.Plugins.Interface.Plugin;
but, allthough i will have alot of methods in the interface, i will have to execute methods that are dynamic, and determined from information in the interface.. so basically, i need to call methods that are not in my interface, and i wont know the name of until last minute..
this is what i have tried (using the "Execute" methods as an example):
plug.GetType().GetMethod("Execute").Invoke((what-the-hell-do-i-put-here), new object[] { });
am i on the right track? please guide me :)
thanks.
If you want to use Reflection then the missing piece in your code is:
MethodInfo meth = plug.GetType().GetMethod("Execute");
meth.Invoke(plug, new object[] { });
The first parameter of the Invoke method should be the instance that you want to invoke the method on. This is required because meth is just an abstract description of the method (and is not associated with any instance). This is useful if you want to call the method on multiple instances (you could cache the meth value).
If you're using C# 4.0, then you can use the new dynamic feature (assuming that "Execute" is a name that does not change):
dynamic plugDynamic = plug;
plugDynamic.Execute( /* arguments */ );
If a variable is declared as dynamic in C# 4.0, then you can call any methods you want and the method resolution will be done at runtime (similar to Reflection, but a bit more complicated and a bit more efficient).

Categories