Class 库(便携式)中的反射 GetMethod 问题
Reflection GetMethod issue in Class Library (Portable)
我有一个 class 库,我在其中定义了几个函数 f1、f2,我想将它们放入字典中以便稍后通过名称调用。但是,即使我使用 System.Reflection,反射 Type.GetMethod 似乎也没有在 class 可移植库中定义。你能建议解决方法吗?
这是我用来演示的简单代码
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;
}
}
我的初衷是把我所有的功能都放在我的字典列表中。我可以手动添加:
list.Add("f1", f1);
list.Add("f2", f2);
但是当我用函数名称声明一个字符串数组时,使用 GetMethod 获取函数,编译器生成错误“类型不包含 GetMethod 的定义...
请指教。
谢谢!
更新:编译错误
单例更新:
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;
}
}
}
首先,大多数 PCL 配置文件都使用 TypeInfo
作为类型信息,参见例如here and here。 TypeInfo
还带有一组略有不同的方法。
所以,而不是写
typeof(Class1).GetMethod(i)
你应该这样写:
typeof(Class1).GetTypeInfo().GetDeclaredMethod(i)
但是即使你使用上面的表达式获得MethodInfo
,你也不能(据我所知)立即将这个对象转换成一个myFunction
委托。
解决此问题的一种方法是使用 expression trees。然后你需要制定一个 Expression<myFunction>
对象,你将编译成一个 myFunction
委托。
我想你可以这样做:
Expression<myFunction> expr =
Expression.Lambda<myFunction>(
Expression.Call(
constrExpr,
typeof(Class1).GetTypeInfo().GetDeclaredMethod(i),
objExpr),
objExpr);
list.Add(i, expr.Compile());
其中 constrExpr
是使用默认构造函数
创建 Class1
实例的表达式
NewExpression constrExpr =
Expression.New(
typeof(Class1).GetTypeInfo().DeclaredConstructors
.Single(ci => ci.GetParameters().Length == 0));
和objExpr
是object o
参数的表示
ParameterExpression objExpr = Expression.Parameter(typeof(object));
通过这些更改,您应该能够调用字典中的任意方法,如下所示:
int i = list["f1"]("hello");
int j = list["f2"](20.0);
我有一个 class 库,我在其中定义了几个函数 f1、f2,我想将它们放入字典中以便稍后通过名称调用。但是,即使我使用 System.Reflection,反射 Type.GetMethod 似乎也没有在 class 可移植库中定义。你能建议解决方法吗?
这是我用来演示的简单代码
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;
}
}
我的初衷是把我所有的功能都放在我的字典列表中。我可以手动添加:
list.Add("f1", f1);
list.Add("f2", f2);
但是当我用函数名称声明一个字符串数组时,使用 GetMethod 获取函数,编译器生成错误“类型不包含 GetMethod 的定义...
请指教。 谢谢!
更新:编译错误
单例更新:
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;
}
}
}
首先,大多数 PCL 配置文件都使用 TypeInfo
作为类型信息,参见例如here and here。 TypeInfo
还带有一组略有不同的方法。
所以,而不是写
typeof(Class1).GetMethod(i)
你应该这样写:
typeof(Class1).GetTypeInfo().GetDeclaredMethod(i)
但是即使你使用上面的表达式获得MethodInfo
,你也不能(据我所知)立即将这个对象转换成一个myFunction
委托。
解决此问题的一种方法是使用 expression trees。然后你需要制定一个 Expression<myFunction>
对象,你将编译成一个 myFunction
委托。
我想你可以这样做:
Expression<myFunction> expr =
Expression.Lambda<myFunction>(
Expression.Call(
constrExpr,
typeof(Class1).GetTypeInfo().GetDeclaredMethod(i),
objExpr),
objExpr);
list.Add(i, expr.Compile());
其中 constrExpr
是使用默认构造函数
Class1
实例的表达式
NewExpression constrExpr =
Expression.New(
typeof(Class1).GetTypeInfo().DeclaredConstructors
.Single(ci => ci.GetParameters().Length == 0));
和objExpr
是object o
参数的表示
ParameterExpression objExpr = Expression.Parameter(typeof(object));
通过这些更改,您应该能够调用字典中的任意方法,如下所示:
int i = list["f1"]("hello");
int j = list["f2"](20.0);