Pass different methods as parameter to invoke by method name - c#

I have several methods in a Util class with different return types and different parameters, f.e:
int RealMethodToExecute(int i, string s) { ... }
Those methods must be invoked in the ui thread and the call would look something like that:
int x = (int)InvokeControl.Invoke("Util.RealMethodToExecute");
Because in my opinion using the method names as string is not really pretty, i thought at the following solution:
public int WrappedRealMethodToExecute(int i, string s)
{
return InvokeMethod(Util.RealMethodToExecute, i, s);
}
private static T InvokeMethod<T>(Func<int, string, T> func, params object[] p)
{
return (T)InvokeControl.Invoke(func.Method.DeclaringType.FullName + "." + func.Method.Name, p);
}
The problem now is that InvokeMethod only acceppts methods with an int and a string parameter and a return value but i have different methods which i want to execute.
I dont want to overload InvokeMethod. I just need the full qualified name of the function to execute it.
Any ideas??
edit: extended example with parameters

Fankly, this might as well be just:
private static object InvokeMethod(Delegate method, params object[] args)
{
return InvokeControl.Invoke(method, args);
}
where InvokeControl.Invoke uses (to get to the UI thread):
someControl.Invoke(method, args);

Related

Invoke Function with async method delegate in C# [duplicate]

I have several methods all with the same parameter types and return values but different names and blocks. I want to pass the name of the method to run to another method that will invoke the passed method.
public int Method1(string)
{
// Do something
return myInt;
}
public int Method2(string)
{
// Do something different
return myInt;
}
public bool RunTheMethod([Method Name passed in here] myMethodName)
{
// Do stuff
int i = myMethodName("My String");
// Do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
This code does not work but this is what I am trying to do. What I don't understand is how to write the RunTheMethod code since I need to define the parameter.
You can use the Func delegate in .NET 3.5 as the parameter in your RunTheMethod method. The Func delegate allows you to specify a method that takes a number of parameters of a specific type and returns a single argument of a specific type. Here is an example that should work:
public class Class1
{
public int Method1(string input)
{
//... do something
return 0;
}
public int Method2(string input)
{
//... do something different
return 1;
}
public bool RunTheMethod(Func<string, int> myMethodName)
{
//... do stuff
int i = myMethodName("My String");
//... do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
}
You need to use a delegate. In this case all your methods take a string parameter and return an int - this is most simply represented by the Func<string, int> delegate1. So your code can become correct with as simple a change as this:
public bool RunTheMethod(Func<string, int> myMethodName)
{
// ... do stuff
int i = myMethodName("My String");
// ... do more stuff
return true;
}
Delegates have a lot more power than this, admittedly. For example, with C# you can create a delegate from a lambda expression, so you could invoke your method this way:
RunTheMethod(x => x.Length);
That will create an anonymous function like this:
// The <> in the name make it "unspeakable" - you can't refer to this method directly
// in your own code.
private static int <>_HiddenMethod_<>(string x)
{
return x.Length;
}
and then pass that delegate to the RunTheMethod method.
You can use delegates for event subscriptions, asynchronous execution, callbacks - all kinds of things. It's well worth reading up on them, particularly if you want to use LINQ. I have an article which is mostly about the differences between delegates and events, but you may find it useful anyway.
1 This is just based on the generic Func<T, TResult> delegate type in the framework; you could easily declare your own:
public delegate int MyDelegateType(string value)
and then make the parameter be of type MyDelegateType instead.
From OP's example:
public static int Method1(string mystring)
{
return 1;
}
public static int Method2(string mystring)
{
return 2;
}
You can try Action Delegate! And then call your method using
public bool RunTheMethod(Action myMethodName)
{
myMethodName(); // note: the return value got discarded
return true;
}
RunTheMethod(() => Method1("MyString1"));
Or
public static object InvokeMethod(Delegate method, params object[] args)
{
return method.DynamicInvoke(args);
}
Then simply call method
Console.WriteLine(InvokeMethod(new Func<string,int>(Method1), "MyString1"));
Console.WriteLine(InvokeMethod(new Func<string, int>(Method2), "MyString2"));
In order to provide a clear and complete answer, I'm going to start from the very beginning before showing three possible solutions.
A brief introduction
All .NET languages (such as C#, F#, and Visual Basic) run on top of the Common Language Runtime (CLR), which is a VM that runs code in the Common Intermediate Language (CIL), which is way higher level than machine code. It follows that methods aren't Assembly subroutines, nor are they values, unlike functional languages and JavaScript; rather, they're symbols that CLR recognizes. Not being values, they cannot be passed as a parameter. That's why there's a special tool in .NET. That is, delegates.
What's a delegate?
A delegate represents a handle to a method (the term handle is to be preferred over pointer as the latter would be an implementation detail). Since a method is not a value, there has to be a special class in .NET, namely Delegate, which wraps up any method. What makes it special is that, like very few classes, it needs to be implemented by the CLR itself and couldn't be simply written as a class in a .NET language.
Three different solutions, the same underlying concept
The type–unsafe way
Using the Delegate special class directly.
Example:
static void MyMethod()
{
Console.WriteLine("I was called by the Delegate special class!");
}
static void CallAnyMethod(Delegate yourMethod)
{
yourMethod.DynamicInvoke(new object[] { /*Array of arguments to pass*/ });
}
static void Main()
{
CallAnyMethod(MyMethod);
}
The drawback here is your code being type–unsafe, allowing arguments to be passed dynamically, with no constraints.
The custom way
Besides the Delegate special class, the concept of delegates spreads to custom delegates, which are declarations of methods preceded by the delegate keyword. They are type–checked the same way as “normal” method invocations, making for type-safe code.
Example:
delegate void PrintDelegate(string prompt);
static void PrintSomewhere(PrintDelegate print, string prompt)
{
print(prompt);
}
static void PrintOnConsole(string prompt)
{
Console.WriteLine(prompt);
}
static void PrintOnScreen(string prompt)
{
MessageBox.Show(prompt);
}
static void Main()
{
PrintSomewhere(PrintOnConsole, "Press a key to get a message");
Console.Read();
PrintSomewhere(PrintOnScreen, "Hello world");
}
The standard library's way
Alternatively, you can stick with a delegate that's part of the .NET Standard:
Action wraps up a parameterless void method;
Action<T1> wraps up a void method with one parameter of type T1;
Action<T1, T2> wraps up a void method with two parameters of types T1 and T2, respectively,
and so forth;
Func<TR> wraps up a parameterless function with TR return type;
Func<T1, TR> wraps up a function with TR return type and with one parameter of type T1;
Func<T1, T2, TR> wraps up a function with TR return type and with two parameters of types T1 and T2, respectively;
and so forth.
However, bear in mind that by using predefined delegates like these, parameter names won't be self-describing, nor is the name of the delegate type meaningful as to what instances are supposed to do. Therefore, refrain from using them in contexts where their purpose is not absolutely self-evident.
The latter solution is the one most people posted. I'm also mentioning it in my answer for the sake of completeness.
The solution involves Delegates, which are used to store methods to call. Define a method taking a delegate as an argument,
public static T Runner<T>(Func<T> funcToRun)
{
// Do stuff before running function as normal
return funcToRun();
}
Then pass the delegate on the call site:
var returnValue = Runner(() => GetUser(99));
You should use a Func<string, int> delegate, that represents a function taking a string argument and returning an int value:
public bool RunTheMethod(Func<string, int> myMethod)
{
// Do stuff
myMethod.Invoke("My String");
// Do stuff
return true;
}
Then invoke it this way:
public bool Test()
{
return RunTheMethod(Method1);
}
While the accepted answer is absolutely correct, I would like to provide an additional method.
I ended up here after doing my own searching for a solution to a similar question.
I am building a plugin driven framework, and as part of it I wanted people to be able to add menu items to the applications menu to a generic list without exposing an actual Menu object because the framework may deploy on other platforms that don't have Menu UI objects. Adding general info about the menu is easy enough, but allowing the plugin developer enough liberty to create the callback for when the menu is clicked was proving to be a pain. Until it dawned on me that I was trying to re-invent the wheel and normal menus call and trigger the callback from events!
So the solution, as simple as it sounds once you realize it, eluded me until now.
Just create separate classes for each of your current methods, inherited from a base if you must, and just add an event handler to each.
Here is an example Which can help you better to understand how to pass a function as a parameter.
Suppose you have Parent page and you want to open a child popup window. In the parent page there is a textbox that should be filled basing on child popup textbox.
Here you need to create a delegate.
Parent.cs
// declaration of delegates
public delegate void FillName(String FirstName);
Now create a function which will fill your textbox and function should map delegates
//parameters
public void Getname(String ThisName)
{
txtname.Text=ThisName;
}
Now on button click you need to open a Child popup window.
private void button1_Click(object sender, RoutedEventArgs e)
{
ChildPopUp p = new ChildPopUp (Getname) //pass function name in its constructor
p.Show();
}
IN ChildPopUp constructor you need to create parameter of 'delegate type' of parent //page
ChildPopUp.cs
public Parent.FillName obj;
public PopUp(Parent.FillName objTMP)//parameter as deligate type
{
obj = objTMP;
InitializeComponent();
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
obj(txtFirstName.Text);
// Getname() function will call automatically here
this.DialogResult = true;
}
If you want to pass Method as parameter, use:
using System;
public void Method1()
{
CallingMethod(CalledMethod);
}
public void CallingMethod(Action method)
{
method(); // This will call the method that has been passed as parameter
}
public void CalledMethod()
{
Console.WriteLine("This method is called by passing it as a parameter");
}
If the method passed needs to take one argument and return a value, Func is the best way to go. Here is an example.
public int Method1(string)
{
// Do something
return 6;
}
public int Method2(string)
{
// Do something different
return 5;
}
public bool RunTheMethod(Func<string, int> myMethodName)
{
// Do stuff
int i = myMethodName("My String");
Console.WriteLine(i); // This is just in place of the "Do more stuff"
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
Read the docs here
However, if your method that is passed as a parameter does not return anything, you can also use Action. It supports up to 16 paramaters for the passed method. Here is an example.
public int MethodToBeCalled(string name, int age)
{
Console.WriteLine(name + "'s age is" + age);
}
public bool RunTheMethod(Action<string, int> myMethodName)
{
// Do stuff
myMethodName("bob", 32); // Expected output: "bob's age is 32"
return true;
}
public bool Test()
{
return RunTheMethod(MethodToBeCalled);
}
Read the documentation here
Here is an example without a parameter:
http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string
with params:
http://www.daniweb.com/forums/thread98148.html#
you basically pass in an array of objects along with name of method. you then use both with the Invoke method.
params Object[] parameters
class PersonDB
{
string[] list = { "John", "Sam", "Dave" };
public void Process(ProcessPersonDelegate f)
{
foreach(string s in list) f(s);
}
}
The second class is Client, which will use the storage class. It has a Main method that creates an instance of PersonDB, and it calls that object’s Process method with a method that is defined in the Client class.
class Client
{
static void Main()
{
PersonDB p = new PersonDB();
p.Process(PrintName);
}
static void PrintName(string name)
{
System.Console.WriteLine(name);
}
}
I don't know who might need this, but in case you're unsure how to send a lambda with a delegate, when the function using the delegate doesn't need to insert any params in there you just need the return value.
SO you can also do this:
public int DoStuff(string stuff)
{
Console.WriteLine(stuff);
}
public static bool MethodWithDelegate(Func<int> delegate)
{
///do stuff
int i = delegate();
return i!=0;
}
public static void Main(String[] args)
{
var answer = MethodWithDelegate(()=> DoStuff("On This random string that the MethodWithDelegate doesn't know about."));
}

How can I deconstruct a function call when passing it as an argument to another function

I would like to pass a function that returns two values to another function that expects the same two values as parameters. In the example below I want to pass GetNum To GetLine.
public class Program
{
public static void Main()
{
Console.WriteLine(GetLine(GetNum()));
}
public static (int,string) GetNum() => (5,"five");
public string GetLine(int n , string s) => $"{n} {s}";
}
Is there any C# syntax that can help me?
Functions only return one value (i.e. one Type), in this case GetNum is returning a ValueTuple<int, string>.
One way to allow the GetLine method to work with the return type of GetNum is to write an overload of the method that takes a ValueTuple<int, string> and returns the result of passing Item1 and Item2 to the original method:
public string GetLine((int, string) t) => GetLine(t.Item1, t.Item2);
Now you can use the return value of one method as an argument to the second:
var result = GetLine(GetNum());
You can do something like this:
public static void Main()
{
Console.WriteLine(GetLine(GetNum()));
}
public static (int,string) GetNum() => (5,"five");
public static string GetLine((int, string) a) {
var (number, text) = a;
return $"{number}, {text}";
}
Why does this work? The (int, string) in argument of GetLine function is actually a type, just like float or double. Therefore it makes no sense to actually deconstruct it in place. When writing function argument, you are not expected to write any logic there - you cannot for example increment a number there. You are expected just to list argument types and names of the arguments.
There is no C# syntax that will do literally what you want. A method that has two parameters, such as your GetLine() method, needs to have two arguments passed to it, and C# doesn't provide a way to deconstruct tuples except into specific variables. Since arguments to a method are just values (with the exception of by-reference arguments), there's no variable into which to deconstruct your tuple.
There are lots of different ways to do something similar. However, IMHO the closest to what you want to do would look something like this:
static class Extensions
{
public static TResult CallDeconstructed<T1, T2, TResult>(this (T1, T2) tuple, Func<T1, T2, TResult> func)
{
return func(tuple.Item1, tuple.Item2);
}
}
I.e. an extension method you can call on the tuple, which will pass the tuple's individual values as separate method arguments to the provided method. Used something like this:
public static void Main()
{
//Console.WriteLine(GetLine(GetNum()));
Console.WriteLine(GetNum().CallDeconstructed(GetLine));
}
public static (int, string) GetNum() => (5, "five");
public static string GetLine(int n, string s) => $"{n} {s}";
All that said, I'm not sure that any of the alternatives, including the above, is really all that much better than writing the intermediate code at the call site:
(int n, string s) = GetNum();
GetLine(n, s);
There is a template for that -- it looks like :
public static string GetLine(Action<string, int> passedProc, otherParms) // etc
this takes a Proc.
For a function you do it like this
public static string GetLine(Function<(string, int)> passedFunc, otherParms) // etc
Then you can call passedFunc in your GetLine procedure and get the tuple back.

C# methods with variable paramterlist as parameter

Hi I'm currently trying to pass methods (with no return value) as parameters to another method (so that they can be called from within the methods).
The problem I'm currently having is, that I'm using Action in the parameterlist and thus need to exactly define which parameters this method takes.
The question thus is: Is there any way to omit this? Thus that I don't have to define which parameters exactly the method has in the parameterdeclaration?
Codeexample:
public void A(int myint)
{
Console.WriteLine(myint.ToString());
}
public void B(int myint1, int myint2)
{
Console.WriteLine((myint1 + myint2).ToString());
}
public void myQuestionMethod(Action<int> parameterMethod)
{
//....Dosomething special by creating the parameters within and calling the given methods
}
myQuestionMethod(A);
myQuestionMethod(B);
Thus Aciton parameterMethod can that be replaced by something else that allows me to give methods as parameters who have differing parameters?
Edit:
I forgot to mention that the TYPE of the parameters is also not fixated.
Thus a function C could exist with (int param1, String param2)
No. There is no way to do this with the Action delegate (that's why there are 16 overloads).
You could opt, if the variables are all of the same type and have the same meaning, to create an array of integers:
public void A(params int[] myint)
{
}
public void myQuestionMethod(Action<int[]> parameterMethod)
{
//....Dosomething special by creating the parameters within and calling the given methods
}
Depending on how big your methods are, you could go for just Action and use anonymous methods rather than explicitly defining the functions
public void myQuestionMethod(Action parameterMethod)
{
//
}
...
myQuestionMethod(() => Console.WriteLine(myInt.ToString()));
myQuestionMethod(() => Console.WriteLine((myInt1 + myInt2).ToString()));
One solution would be to use reflection. Of course don't use it unless you do not have any other choice (specifying a method using its name should be avoided if possible):
public class Foo
{
public void A(int myint)
{
Console.WriteLine(myint.ToString());
}
public void B(int myint1, int myint2)
{
Console.WriteLine((myint1 + myint2).ToString());
}
public void myQuestionMethod(string parameterMethodName, params object[] parameters)
{
var method = this.GetType().GetMethod(parameterMethodName, BindingFlags.Instance | BindingFlags.Public);
method.Invoke(this, parameters);
}
}
public class Test
{
public static void Main()
{
var foo = new Foo();
foo.myQuestionMethod("B", 1, 2);
Console.Read();
}
}

Extension method for string array and params

How can I get both these two methods to compile?
public static IEnumerable<string> DoSomething(params string[] args)
{ // do something }
public static IEnumerable<string> DoSomething(this string[] args)
{ // do something }
I get this compile error:
Type 'Extensions' already defines a member called 'DoSomething' with the same parameter types Extensions.cs
So that I can do this:
new string[] { "", "" }.DoSomething();
Extensions.DoSomething("", "");
Without the params method, I have to do this:
Extensions.DoSomething(new string[] { "", "" });
Update: Based on the answer by O. R. Mapper
public static IEnumerable<string> DoSomething(string arg, params string[] args)
{
// args null check is not required
string[] argscopy = new string[args.Length + 1];
argscopy[0] = arg;
Array.Copy(args, 0, argscopy, 1, args.Length);
return argscopy.DoSomething();
}
Update: I like HugoRune's answer now.
You can add an additional parameter to the params version:
public static IEnumerable<string> DoSomething(string firstArg, params string[] moreArgs)
That should be sufficient for the compiler to distinguish it from the string[] extension method.
As suggested by user SLaks, an additional overload without any arguments should be provided in this case, if the situation with an empty params array needs to be supported:
public static IEnumerable<string> DoSomething()
Late answer:
Another option is to just put both methods in different classes. Since you never us the class name when calling the extension method (the one with the this parameter), the extension method can be in any public static class in the same namespace, without any noticeable difference.
// contains static methods to help with strings
public static class StringTools
{
public static IEnumerable<string> DoSomething(params string[] args)
{
// do something
}
}
// contains only extension methods
public static class StringToolsExtensions
{
public static IEnumerable<string> DoSomething(this string[] args)
{
return StringTools.DoSomething(args);
}
}
This way you avoid copying the string array, you do not need an additional overload with no arguments, and I would say it looks cleaner. I would always separate extension methods and other static methods to avoid confusion.
You can give one of the two methods a different name. i.e. DoSomething2
You can just use one method. It's the same method with the same parameter list; clearly they're doing the same thing (since you didn't give them different names as per #1). Just combine them.
You can change the parameter list of one of the methods. i.e. (this string[] args, object unusedParameter)

(How) is it possible to bind/rebind a method to work with a delegate of a different signature?

I'm a c++ developer having used signals & slots in c++ which to me seems to be analogous to delegates in c#. I've found myself at a loss in searching for the functionality provided by "bind", and feel I must be missing something.
I feel like that something like the following, which is possible in c++ should be possible in c# with delegates. Here is some psudo-code for what I would do in c++:
Slot<void> someCallback;
int foo(int i)
{
std::cout << "Value: " << i << "\n";
return i;
}
int main()
{
int i = 0;
Slot<int> someCallback = bind( fun_ptr(foo), i );
++i; // added to show that late evaluation would be a non-trivial difference
int result = someCallback();
assert( result == 0 );
return 0;
}
Unfortunately, I've not been able to find any reference to binding/rebinding with regards to c# delegates. Am I missing something? Is there some radically different way to do this in c#?
In C# we do something like this:
class Program {
static Action Curry<T>(Action<T> action, T parameter) {
return () => action(parameter);
}
static void Foo(int i) {
Console.WriteLine("Value: {0}", i);
}
static void Main(string[] args) {
Action curried = Curry(Foo, 5);
curried();
}
}
Clearly the method Foo corresponds to your method Foo, just with the appropriate calls to Console.WriteLine instead of std::cout.
Next, we declare a method Curry that accepts an Action<T> and returns an Action. In general, an Action<T> is a delegate that accepts a single parameter of type T and returns void. In particular, Foo is an Action<int> because it accepts one parameter of type int and returns void. As for the return type of Curry, it is declared as an Action. An Action is a delegate the has no parameters and returns void.
The definition of Curry is rather interesting. We are defining an action using a lambda expression which is a very special form of an anonymous delegate. Effectively
() => action(parameter)
says that the void parameter is mapped to action evaluated at parameter.
Finally, in Main we are declaring an instance of Action named curried that is the result of applying Curry to Foo with the parameter 5. This plays the same role as bind(fun_ptr(foo), 5) in your C++ example.
Lastly, we invoke the newly formed delegate curried via the syntax curried(). This is like someCallback() in your example.
The fancy term for this is currying.
As a more interesting example, consider the following:
class Program {
static Func<TArg, TResult> Curry<TArg, TResult>(
Func<TArg, TArg, TResult> func,
TArg arg1
) {
return arg => func(arg1, arg);
}
static int Add(int x, int y) {
return x + y;
}
static void Main(string[] args) {
Func<int, int> addFive = Curry<int, int>(Add, 5);
Console.WriteLine(addFive(7));
}
}
Here we are declaring a method Curry that accepts a delegate (Func<TArg, TArg, TResult> that accepts two parameters of the same type TArg and returns a value of some other type TResult and a parameter of type TArg and returns a delegate that accepts a single parameter of type TArg and returns a value of type TResult (Func<TArg, TResult>).
Then, as a test we declare a method Add that accepts two parameters of type int and returns a parameter of type int (a Func<int, int, int>). Then in Main we instantiate a new delegate named addFive that acts like a method that adds five to its input parameter. Thus
Console.WriteLine(addFive(7));
prints 12 on the console.
Try the following
class Example {
static void foo(int i) {
Console.WriteLine(i);
}
public static void Main() {
Action someCallback = () => foo(5);
someCallback();
}
}
Or for something even closer to the C++ counter part
class Example {
static void foo(int i) {
Console.WriteLine(i);
}
static Action bind<T>(Action<T> action, T value) {
return () => action(value);
}
public static void Main() {
Action someCallback = bind(foo, 5);
someCallback();
}
}
Explanation. What's happening here is that I am creating a new delegate by means of a lambda expression. The lambda is the expression starting with () =>. In this case it creates a delegate accepting no arguments and producing no value. It is compatible with the type Action.

Categories