The title is may be not clear enough, but I'll show you a short program in order to make you understand what I want to do:
Class Program
{
private static Obj A = new Obj(...);
private static void Function(AnyMethodOfMyObject() m)
{
object[] result = A.m();
...
}
static void main()
{
double a,b,c = 0;
string d = " ";
Function(MethodX(a,b,c));
Function(MethodY(d,a,b));
...
}
}
The methods will always return the same type which is an object[], but I don't have the same number/type of argument.
Thanks !
You can do this simply with a Func<object[]>:
class Program
{
private static Obj A = new Obj(...);
private static void Function(Func<object[]> m)
{
object[] result = m();
...
}
static void main()
{
double a,b,c = 0;
string d = " ";
Function(() => A.MethodX(a,b,c));
Function(() => A.MethodY(d,a,b));
...
}
}
Func<object[]> is a delegate (broadly, a reference to a method) which does not take any parameters, and which returns an array of objects. While MethodX takes 3 parameters (a,b,c), we can create a new anonymous method without doesn't take any parameters itself, and which just calls MethodX and passes in the values of a, b and c (they're captured at the point that we create this new anonymous method). This is what () => MethodX(a, b, c) does.
If you have different Obj instances and you want to control which one the method is called on, then use a Func<Obj, object[]>. This takes an Obj as a parameter, and returns an object[] as before.
class Program
{
private static Obj A = new Obj(...);
private static void Function(Func<Obj, object[]> m)
{
object[] result = m(A);
...
}
static void main()
{
double a,b,c = 0;
string d = " ";
Function(x => x.MethodX(a,b,c));
Function(x => x.MethodY(d,a,b));
...
}
}
Related
namespace PickOverload;
class Program {
delegate string Formatter( object o );
string Show( double a ) { return a.ToString(); }
string Show( int a ) { return a.ToString(); }
string Format( Formatter f, object o ) { return f( o ); }
void SelectArgument() {
// error CS1503: Argument 1: cannot convert from 'method group' to 'Program.Formatter'
Format( Show, 1.234 );
}
void SelectDelegate() {
// error CS0123: No overload for 'Show' matches delegate 'Program.Formatter
Formatter x = this.Show;
}
void Run() {
SelectArgument();
SelectDelegate();
}
static void Main( string[] args ) {
new Program().Run();
}
}
Is there a C# syntax for picking one of the overloaded Show methods as argument for the Format method or for the delegate?
I'm not looking for a solution for the above sample, but for ways to pick one of multiple overloaded methods for delegates or method arguments.
Same problem here:
void Run() {
double f = 1.234;
Format( Show, f );
Formatter x = this.Show;
}
static void Main(string[] args ) {
new Program().Run();
}
You can do this with generics, for example:
internal delegate string Formatter<T>(T o);
internal static string Show(double a) => a.ToString();
internal static string Show(int a) => a.ToString();
internal static string Format<T>(Formatter<T> f, T o) => f(o);
static void Main(string[] args)
{
double f = 1.234;
Format(Show, f);
}
void foo(int one, int two) {
}
public static void Main(string[] args) {
var bar = new int[] { 1, 2 };
foo(params bar);
}
What's the correct syntax to deconstruct the bar array and pass it as the arguments to the foo method?
In some other languages you can use a splat operator foo(...bar) or an unpack operator foo(*bar).
How can I do it in C#?
There isn't an equivalent function in C#. Each argument has to be passed individually.
There are, of course, work arounds that you likely already know. You could declare an overload for your function that would accept an array and call the original function using the first two inputs. The other alternative that I can think of is to declare the function parameter with the params keyword so that it could receive an array or multiple conma-separated elements when called.
void foo(params int[] numbers)
{ // TODO: Validate numbers length
int one = numbers[0];
int two = numbers[1];
}
public static void Main(string[] args) {
var bar = new int[] { 1, 2 };
// both valid function calls below
foo(bar);
foo(bar[0], bar[1]);
}
You can always use Reflection for such purpose.
Here is example snippet on your example method:
class MainClass
{
void foo(int one, int two)
{
Console.WriteLine(one + two);
}
static void Main()
{
var myInstance = new MainClass();
var bar = new object[] { 1, 2 };
var method = myInstance.GetType().GetMethod(nameof(MainClass.foo), BindingFlags.NonPublic | BindingFlags.Instance)
?? throw new InvalidOperationException($"Method '{nameof(MainClass.foo)}' not found");
method.Invoke(myInstance, bar) ;
}
}
I have something like this. How can i return value form anonymous method?
returnRate = d;. For example let i have some class which get's messages from server. I want to process those messages in classes Cars and Bicycles is that clearly now?
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
Cars c = new Cars();
Bicycles b = new Bicycles();
}
}
public class Cars
{
public Cars()
{
GetData G1 = new GetData();
Dictionary<string, string> D1 = new Dictionary<string, string>();
G1.ProcessCars(ref D1);
}
}
public class Bicycles
{
public Bicycles()
{
GetData G2 = new GetData();
Dictionary<string, string> D2 = new Dictionary<string, string>();
G2.ProcessBicycles(ref D2);
}
}
public class Singleton
{
private static Singleton instance;
public Dictionary<string, Action<MessageEventArgs>> Handle;
private Singleton()
{
Handle = new Dictionary<string, Action<MessageEventArgs>>();
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
public class GetData
{
private Client socket;
public GetData()
{
socket = new Client("http://echo.jsontest.com/bicycles/10");
socket.Message += Message;
}
public void ProcessBicycles(ref Dictionary<string, string> returnRate)
{
Singleton.Instance.Handle.Add("bicycles", (m) =>
{
Dictionary<string, string> d = m.Message.Json.GetFirstArgAs<Dictionary<string, string>>() as Dictionary<string, string>;
//returnRate = d;
});
}
public void ProcessCars(ref Dictionary<string, string> returnRate)
{
Singleton.Instance.Handle.Add("cars", (m) =>
{
Dictionary<string, string> d = m.Message.Json.GetFirstArgAs<Dictionary<string, string>>() as Dictionary<string, string>;
//returnRate = d;
});
}
private void Message(object sender, MessageEventArgs e)
{
if (Singleton.Instance.Handle.ContainsKey(e.Message.Event))
{
Singleton.Instance.Handle[e.Message.Event](e);
}
}
}
}
You'll have to pass in the Action yourself, rather than creating it with a ref parameter. So your Add method simply becomes:
public void Add(Action<string> action) {
Handle.Add("1", action);
}
You can call it like this:
Add(m => ReturnRate = m);
This is a kind of Callback function, which can be used for a kind of asynchronous programming. However, it might be worth your time to read about async and await. If you could give us more information about what your scenario exactly is, we might be able to give you more hints.
If you have to use a ref parameter (for some strange reason), I think you're out of luck...
You should use Func<string,string> instead Action
Action<string> means void function(string s)
Func<string,string> means string function(string s)
However it depends on usage you want to achieve.
This is because the used variables that are used in the the anonymous method body but are outside of it, will be public fields in the generated class made by the compiler. But you can introduce a local variable to make it compilable:
public void Add(ref string rate)
{
string r = rate;
Handle.Add("1", (m) =>
{
Console.WriteLine(m);
r = m;
});
rate = r;
}
And the compiler will generate this in the background:
public void Add(ref string rate)
{
<>c__DisplayClass1 CS$<>8__locals2 = new <>c__DisplayClass1();
CS$<>8__locals2.r = rate;
this.Handle.Add("1", new Action<string>(CS$<>8__locals2.<Add>b__0));
rate = CS$<>8__locals2.r;
}
[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
public string r;
public void <Add>b__0(string m)
{
Console.WriteLine(m);
this.r = m;
}
}
Note: Though this can be compiled, it will not work as you expect, because calling the outer Add will not execute the delegate added by Handle.Add. To return the m from the inner delegate you must use a Func instead.
You should use Func<string,string> (delegate Func<in T,out TResult>) which is equivalent to some function that takes in string and returns string
for eg:-
private string MyFunction(string inputstring){}
Whereas Action<string> (delegate Action<in T>) corresponds to a function which only takes input and returns nothing
private void MyFunction(string inputstring){}
You can modify your code to something like
private Dictionary<string, Func<string,string>> Handle;
private string ReturnRate;
public data()
{
Handle = new Dictionary<string, Func<string,string>>();
Add(ref ReturnRate);
Handle["1"]("MyValue");
Console.WriteLine(ReturnRate);
}
public void Add(ref string rate)
{
string somevalue=rate;
Handle.Add("1", (m) =>
{
Console.WriteLine(m);
somevalue= m;
return m;
});
}
I suppose in some ways either (or both) Delegate or MethodInfo qualify for this title. However, neither provide the syntactic niceness that I'm looking for. So, in short, Is there some way that I can write the following:
FunctionPointer foo = // whatever, create the function pointer using mechanisms
foo();
I can't use a solid delegate (ie, using the delegate keyword to declare a delegate type) because there is no way of knowing till runtime the exact parameter list. For reference, here's what I've been toying with in LINQPad currently, where B will be (mostly) user generated code, and so will Main, and hence for nicety to my users, I'm trying to remove the .Call:
void Main()
{
A foo = new B();
foo["SomeFuntion"].Call();
}
// Define other methods and classes here
interface IFunction {
void Call();
void Call(params object[] parameters);
}
class A {
private class Function : IFunction {
private MethodInfo _mi;
private A _this;
public Function(A #this, MethodInfo mi) {
_mi = mi;
_this = #this;
}
public void Call() { Call(null); }
public void Call(params object[] parameters) {
_mi.Invoke(_this, parameters);
}
}
Dictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
public A() {
List<MethodInfo> ml = new List<MethodInfo>(this.GetType().GetMethods());
foreach (MethodInfo mi in typeof(Object).GetMethods())
{
for (int i = 0; i < ml.Count; i++)
{
if (ml[i].Name == mi.Name)
ml.RemoveAt(i);
}
}
foreach (MethodInfo mi in ml)
{
functions[mi.Name] = mi;
}
}
public IFunction this[string function] {
get {
if (!functions.ContainsKey(function))
throw new ArgumentException();
return new Function(this, functions[function]);
}
}
}
sealed class B : A {
public void SomeFuntion() {
Console.WriteLine("SomeFunction called.");
}
}
You say you want to keep the number and type of parameters open, but you can do that with a delgate:
public delegate object DynamicFunc(params object[] parameters);
This is exactly the same thing you currently have. Try this:
class Program
{
static void Main(string[] args)
{
DynamicFunc f = par =>
{
foreach (var p in par)
Console.WriteLine(p);
return null;
};
f(1, 4, "Hi");
}
}
You can think of an instance-method delegate as very similar to your Function class: an object an a MethodInfo. So there's no need to rewrite it.
Also function pointers in C and C++ are not any closer to what you need: they cannot be bound to an object instance and function, and also they are statically typed, not dynamically typed.
If you want to "wrap" any other method in a DynamicFunc delegate, try this:
public static DynamicFunc MakeDynamicFunc(object target, MethodInfo method)
{
return par => method.Invoke(target, par);
}
public static void Foo(string s, int n)
{
Console.WriteLine(s);
Console.WriteLine(n);
}
and then:
DynamicFunc f2 = MakeDynamicFunc(null, typeof(Program).GetMethod("Foo"));
f2("test", 100);
Note that I'm using a static method Foo so I pass null for the instance, but if it was an instance method, I'd be passing the object to bind to. Program happens to be the class my static methods are defined in.
Of course, if you pass the wrong argument types then you get errors at runtime. I'd probably look for a way to design your program so that as much type information is captured at compile time as possible.
Here's another bit of code you could use; Reflection is rather slow, so if you expect your Dynamic function calls to be called frequently, you don't want method.Invoke inside the delegate:
public delegate void DynamicAction(params object[] parameters);
static class DynamicActionBuilder
{
public static void PerformAction0(Action a, object[] pars) { a(); }
public static void PerformAction1<T1>(Action<T1> a, object[] p) {
a((T1)p[0]);
}
public static void PerformAction2<T1, T2>(Action<T1, T2> a, object[] p) {
a((T1)p[0], (T2)p[1]);
}
//etc...
public static DynamicAction MakeAction(object target, MethodInfo mi) {
Type[] typeArgs =
mi.GetParameters().Select(pi => pi.ParameterType).ToArray();
string perfActName = "PerformAction" + typeArgs.Length;
MethodInfo performAction =
typeof(DynamicActionBuilder).GetMethod(perfActName);
if (typeArgs.Length != 0)
performAction = performAction.MakeGenericMethod(typeArgs);
Type actionType = performAction.GetParameters()[0].ParameterType;
Delegate action = Delegate.CreateDelegate(actionType, target, mi);
return (DynamicAction)Delegate.CreateDelegate(
typeof(DynamicAction), action, performAction);
}
}
And you could use it like this:
static class TestDab
{
public static void PrintTwo(int a, int b) {
Console.WriteLine("{0} {1}", a, b);
Trace.WriteLine(string.Format("{0} {1}", a, b));//for immediate window.
}
public static void PrintHelloWorld() {
Console.WriteLine("Hello World!");
Trace.WriteLine("Hello World!");//for immediate window.
}
public static void TestIt() {
var dynFunc = DynamicActionBuilder.MakeAction(null,
typeof(TestDab).GetMethod("PrintTwo"));
dynFunc(3, 4);
var dynFunc2 = DynamicActionBuilder.MakeAction(null,
typeof(TestDab).GetMethod("PrintHelloWorld"));
dynFunc2("extraneous","params","allowed"); //you may want to check this.
}
}
This will be quite a bit faster; each dynamic call will involve 1 typecheck per param, 2 delegate calls, and one array construction due to the params-style passing.
I am using reflection class to invoke some methods which are on the some other dll.
And one of the methods' parameters are type of delegate.
And I want to invoke this methods by using reflection.
So I need to pass function parameters as object array, but I could not find anything about
how to convert delegate to object.
Thanks in advance
A delegate is an object. Just create the expected delegate as you would normally, and pass it in the parameters array. Here is a rather contrived example:
class Mathematician {
public delegate int MathMethod(int a, int b);
public int DoMaths(int a, int b, MathMethod mathMethod) {
return mathMethod(a, b);
}
}
[Test]
public void Test() {
var math = new Mathematician();
Mathematician.MathMethod addition = (a, b) => a + b;
var method = typeof(Mathematician).GetMethod("DoMaths");
var result = method.Invoke(math, new object[] { 1, 2, addition });
Assert.AreEqual(3, result);
}
Instances of delegates are objects, so this code works (C#3 style) :
Predicate<int> p = (i)=> i >= 42;
Object[] arrayOfObject = new object[] { p };
Hope it helps !
Cédric
Here's an example:
class Program
{
public delegate void TestDel();
public static void ToInvoke(TestDel testDel)
{
testDel();
}
public static void Test()
{
Console.WriteLine("hello world");
}
static void Main(string[] args)
{
TestDel testDel = Program.Test;
typeof(Program).InvokeMember(
"ToInvoke",
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
null,
null,
new object[] { testDel });
}
}
I think this blog post:
C# Reflection - Dealing with Remote Objects
answers your question perfectly.
you can see a delegate as variable type "function". the delegate describes the parameters and return value for a matching function.
delegate void Foo(int a); // here a new delegate obj type Foo has been declared
the above example allows 'Foo' to be used as a data type, the only allowed object that can be matched with a variable of type Foo data type is a method with the same signature so:
void MyFunction(int x);
Foo D = MyFunction; // this is OK
void MyOtherFunction(string x);
Foo D = MyOtherFunction; // will yield an error since not same signature.
Once you have assigned a method to a delegate, you can invoke the method via the delegate:
int n = 1;
D( n ); // or D.Invoke( n );