C# methods with variable paramterlist as parameter - c#

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

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."));
}

c# How to detect if a particular method has overloaded versions?

I just need to know if there's a smart way to detect if a particular Type method has overloads or not.
At the moment I'm iterating through methods and searching for DeclaringType+Name ambiguity...but I think it's a bit lame :)
The overload is what happens when you have two methods with the same name but different signatures.
So if we can the method is override by check method name whether more than one.
I would create an extension method IsOverloads to make it.
use the IsOverloads method need to provide at least two parameter
the class Type.
check method name
Using reflection to gets method information from the class, then check the method name greater than one means the method is overload.
public static class Ext {
public static bool IsOverloads(this Type type,string methodName)
{
return IsOverloads(type, methodName, BindingFlags.Public | BindingFlags.Instance);
}
public static bool IsOverloads(this Type type,
string methodName,
BindingFlags flags)
{
var info = type.GetMethods(flags);
return info.Where(o1 => o1.Name == methodName).Count() > 1;
}
}
Here is a simple
public class Program
{
public void Test() { }
public void Test(int a) { }
public void TestNo(int a) { }
public static void Main()
{
Console.WriteLine(typeof(Program).IsOverloads("Test")); //True
Console.WriteLine(typeof(Program).IsOverloads("TestNo")); //false
}
}
c# online

C# Type GetMethod() where parameter order is random

I am trying to get a method of an object, and it works fine if the parameters of the method match the order of the list of parameters I provide. I am trying to avoid this, so I do not have to worry about the order of parameter types in methods across different files. Here is what I have
MethodInfo mi = stateType.GetMethod("Entrance", typesToUse.ToArray());
In my test case, typesToUse only contains two instances of unique interfaces,
IClass1 and IClass2 in that order.
If the Entrance method is : Entrance(IClass1 c1, IClass2 c2), it picks this method up. Although, if its Entrance(IClass2 c2, IClass1 c1), it will not and mi will then be null.
Is there a way around this? Perhaps a way to tell GetMethod to ignore parameter order?
Any help is appreciated and thank you.
It is not sensible to implement a method that will ignore parameter order. Parameter order is critical to determining that you have found the correct method.
Consider this simple class:
public class A
{
public void Foo(int a, string b)
{
PrintAString();
}
public void Foo(string b, int a)
{
FormatHardDrive();
}
}
If you're method ignored the parameter order...bad things might happen!
Having said all that, it is possible of course. Simply get all the methods with a given name, eliminate all those that do not contain parameters for all the types in typesToUse, and then ensure you only have one.
The following code demonstrates this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
public class Program
{
public static void Main()
{
var typesToUse = new Type[] { typeof(int), typeof(string) };
var methods = typeof(A).GetMethods().Where(m => m.Name == "Foo");
var matchingMethods = methods.Where(m => ContainsAllParameters(m, typesToUse));
Console.WriteLine(matchingMethods.Single());
}
private static bool ContainsAllParameters(MethodInfo method, Type[] typesToUse)
{
var methodTypes = method.GetParameters().Select(p => p.ParameterType).ToList();
foreach(var typeToUse in typesToUse)
{
if (methodTypes.Contains(typeToUse))
{
methodTypes.Remove(typeToUse);
}
else
{
return false;
}
}
return !methodTypes.Any();
}
}
public class A
{
public void Foo(string a, int b)
{
Console.WriteLine("Hello World");
}
}
You could create an overload of the method, that takes the parameters in different order.
The recommended solution would probably just be to make sure they always are passed in the correct order.
If you can't ensure this, you might solve the problem by creating an overload of the method, or by performing some checks as the first thing in the Entrance-method.

Get MethodInfo for any method with any signature (delegate for any signature)

I want to write a method that will analyze custom attributes of any method (with any number of arguments and any return type) knowing only method info.
This function will check if method has specific Attribute. like this: var tmp = methodInfo.GetCustomAttributes(typeof(LineItemAttribute),false); and if it has such attribute It will execute it.And I want to make call of that function really easy to use. So, in example there are three methods and method GetMethodAttributes that I want to call.
class Test
{
public static void Main()
{
}
public void Test1(){}
public void Test2(int a){}
public void Test3(object a, string c, Boolean d);
public void GetMethodAttributes(MethodInfo mi) {}
}
Ideally I want to write something like that
public static void Main()
{
var t = new Test();
GetMethodAttributes(t.Test1);
GetMethodAttributes(t.Test2);
GetMethodAttributes(t.Test3);
}
I don't want to use string representation of the method names as method names may change, like that:
MethodInfo info = type.GetMethod(name);
Do I have any options? Basically I need a way to use delegates for functions with different sinatures
As Chris Sinclair pointed out in the comment above; you can use a delegate without using reflection or expression trees to get the MethodInfo. The downside is that the compiler is not able to infer the generic parameter so you have to specify the delegate type to match the signature of the given method like this:
public class Test
{
public static void Main()
{
var t = new Test();
CheckMethodAttributes<Action>(t.Test1);
CheckMethodAttributes<Action<int>>(t.Test2);
CheckMethodAttributes<Action<object, string, bool>>(t.Test3);
}
public void Test1() { }
public void Test2(int a) { }
public void Test3(object a, string c, bool d) { }
public static void CheckMethodAttributes<T>(T func)
{
MethodInfo method = new MethodOf<T>(func);
// Example attribute check:
var ignoreAttribute = method.GetAttribute<IgnoreAttribute>();
if (ignoreAttribute != null)
{
// Do something here...
}
}
}
This uses two utility classes, the MethodOf<T> for extracting the MethodInfo from the given Delegate and some AttributeUtils to get strongly typed custom attribute retrieval:
public static class AttributeUtils
{
public static bool HasAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.IsDefined(typeof(TAttribute), inherit);
}
public static TAttribute GetAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.GetAttributes<TAttribute>(inherit).FirstOrDefault();
}
public static IEnumerable<TAttribute> GetAttributes<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.GetCustomAttributes(typeof(TAttribute), inherit).Cast<TAttribute>();
}
}
public class MethodOf<T>
{
public MethodOf(T func)
{
var del = func as Delegate;
if (del == null) throw new ArgumentException("Cannot convert func to Delegate.", "func");
Method = del.Method;
}
private MethodInfo Method { get; set; }
public static implicit operator MethodOf<T>(T func)
{
return new MethodOf<T>(func);
}
public static implicit operator MethodInfo(MethodOf<T> methodOf)
{
return methodOf.Method;
}
}
You can do something like this using Expression Trees, where you pass the method via a lambda expression. You do still need to pass stub values for the parameters, however. For a good example of this in action, check out the source code for Moq, which uses this pattern extensively for setting up mock behaviors for unit testing. Just note that this is not a trivial thing to set up. If you need something relatively quick and dirty, your best bet is probably string names with a good refactoring tool and/or automated tests to help deal with the renaming issues.

Get property type to pass to generic method

I need to get the type of a property that will only be known at run time and pass this as a type parameter for a generic method. For example:
PropertyInfo prop = Bar.GetProperty("Property1");
//"type 'prop' could not be found" error
Foo<prop.PropertyType>();
void Foo<T>()
{
//Stuff
}
class Bar
{
string Property1{get;set;}
}
The type of Bar.Property1 will not be known at compile time, so I can't do Foo<string>();. It will compile and run correctly if I use Foo<dynamic>(); but I'm not convinced that's the best way to go, and I'd like to know if there is a way to do it using an older framework.
Hopefully, this more complete example will make my intentions clearer:
public void Map(TInType inObject, TOutType outObject)
{
//propertyIn, propertyOut, and converter are all strings identifying the properties/methods to be used from the inObject/Type outObject/Type.
SetPropertyValues<dynamic, dynamic>(inObject, outObject, propertyIn, propertyOut, converter);
}
private void SetPropertyValues<TPropIn,TPropOut>(TInType fromObject, TOutType toObject, string propertyIn, string propertyOut, string converter)
{
PropertyInfo prop1 = typeof(TInType).GetProperty(propertyIn);
MethodInfo converterMethod = typeof(TInType).GetMethod(converter);
PropertyInfo prop2 = typeof(TOutType).GetProperty(propertyOut);
prop2.SetValue(
toObject,
CopyPropertyValue<TPropIn, TPropOut>((TPropIn)prop1.GetValue(fromObject, null), p => (TPropOut)converterMethod.Invoke(fromObject, new object[] { p })),
null);
}
private TPropOut CopyPropertyValue<TPropIn, TPropOut>(TPropIn InPropValue, Func<TPropIn, TPropOut> converterFunction)
{
return converterFunction(InPropValue);
}
I'm open to any other suggestions anyone may have, or that the code should be taken out back and shot, but my original question is still the one I'm most interested in.
You can use MakeGenericMethod, performance is actually quite reasonable and allows you to explicitly define what you are calling with what, so reduces the overhead.
So something like the following, the Invoker would call the explicit method / class you need, and the helper actually invokes the generic call.
public class GenericHelper
{
public static void DoSomethingGeneric(GenericInvokerParameters parameters)
{
var targetMethodInfo = typeof(GenericInvoker).GetMethod("DoSomethingGeneric");
var genericTargetCall = targetMethodInfo.MakeGenericMethod(parameters.InvokeType);
genericTargetCall.Invoke(new GenericInvoker(), new[] { parameters });
}
}
public class GenericInvoker
{
public void DoSomethingGeneric<T>(GenericInvokerParameters parameters)
{
//Call your generic class / method e.g.
SomeClass.SomeGenericMethod<T>(parameters.SomeValue);
}
}
public class GenericInvokerParameters
{
public GenericInvokerParameters(Type typeToInvoke, string someValue)
{
SomeValue = someValue;
InvokeType = typeToInvoke;
}
public string SomeValue { get; private set; }
public Type InvokeType { get; private set; }
}
Don't see anything bad in dynamic.
Use it.
EDIT
Till you're not going to call that method with high frequency, where the reflection could bit it from performance perspective, I would prefer dynamic
Foo should not be generic if you are not using it generically. Just make it operate on type Object instead of T.

Categories