I have a class library in which I have defined a few functions f1, f2 that I would like to put them in a dictionary to later call by name. However, the reflection Type.GetMethod does not seem to be defined in the class library portable even I am using System.Reflection. Can you suggest a work around?
This is my simple piece of code for illustration
public class Class1
{
public delegate int myFunction(object o);
private Dictionary<string, myFunction> list = new Dictionary<string, myFunction>();
public Class1()
{
string[] n = { "f1", "f2" };
MethodInfo mInfo;
foreach (var i in n)
{
mInfo = typeof(Class1).GetMethod(i);
}
list.Add("f1", f1);
list.Add("f2", f2);
}
public int f1(object o)
{
System.Diagnostics.Debug.WriteLine("f1: parameter is {0} " ,o);
return 0;
}
public int f2(object o)
{
System.Diagnostics.Debug.WriteLine("f2: parameter is {0} ", o);
return 0;
}
}
my original intention was putting all my functions in my dictionary list. I can manually add:
list.Add("f1", f1);
list.Add("f2", f2);
But when I declare an array of string with the name of the function, use GetMethod to pick up the function, compiler was generating an error "Type does not contain definition for GetMethod...
Please advise. Thanks!
Update with Singleton:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace ClassLibrary1
{
public sealed class Class1
{
public delegate int myFunction(object o);
public Dictionary<string, myFunction> list = new Dictionary<string, myFunction>();
private static readonly Class1 _instance = new Class1();
static Class1()
{
}
public Class1()
{
string[] n = { "f1", "f2" };
MethodInfo mInfo;
foreach (var i in n)
{
mInfo = typeof(Class1).GetTypeInfo().GetDeclaredMethod(i);
//NewExpression constrExpr = Expression.New(typeof(Class1).GetTypeInfo().DeclaredConstructors.Single(ci => ci.GetParameters().Length == 0));
ParameterExpression objExpr = Expression.Parameter(typeof(object));
Expression<myFunction> expr = Expression.Lambda<myFunction>(Expression.Call(null, mInfo, objExpr), objExpr);
//Expression<myFunction> expr = Expression.Lambda<myFunction>(Expression.Call(constrExpr, mInfo, objExpr), objExpr);
list.Add(i, expr.Compile());
}
list.Add("f11", f1);
list.Add("f21", f2);
}
public static Class1 Instance
{
get
{
return _instance;
}
}
public int f1(object o)
{
System.Diagnostics.Debug.WriteLine("f1: parameter is {0} ", o);
return 0;
}
public int f2(object o)
{
System.Diagnostics.Debug.WriteLine("f2: parameter is {0} ", o);
return 0;
}
}
}
First of all, most PCL profiles are using TypeInfo
for type information, see e.g. here and here. TypeInfo
also comes with a slightly different set of methods.
So, instead of writing
typeof(Class1).GetMethod(i)
you should thus write:
typeof(Class1).GetTypeInfo().GetDeclaredMethod(i)
But even if you use the above expression to obtain MethodInfo
, you cannot (to my knowledge) immediately convert this object into a myFunction
delegate.
One way of solving this problem would be to use expression trees. You would then need to formulate an Expression<myFunction>
object which you would compile into a myFunction
delegate.
I think you can do something like this:
Expression<myFunction> expr =
Expression.Lambda<myFunction>(
Expression.Call(
constrExpr,
typeof(Class1).GetTypeInfo().GetDeclaredMethod(i),
objExpr),
objExpr);
list.Add(i, expr.Compile());
where constrExpr
is an expression for creating an instance of Class1
using the default constructor
NewExpression constrExpr =
Expression.New(
typeof(Class1).GetTypeInfo().DeclaredConstructors
.Single(ci => ci.GetParameters().Length == 0));
and objExpr
is a representation of the object o
parameter
ParameterExpression objExpr = Expression.Parameter(typeof(object));
With these changes, you should be able to invoke an arbitrary method in your dictionary, like this:
int i = list["f1"]("hello");
int j = list["f2"](20.0);