C# 使用类名和方法名调用类的成员
我试图使用C# 使用类名和方法名调用类的成员,c#,reflection,.net-4.0,C#,Reflection,.net 4.0,我试图使用反射调用类的函数(假设对象初始化不依赖于要调用的函数),如下所示 /// <summary> /// Calls a static public method. /// Assumes that the method returns a string /// </summary> /// <param name="assemblyName">name of the assembly containing the cl
反射调用类的函数(假设对象初始化不依赖于要调用的函数),如下所示
/// <summary>
/// Calls a static public method.
/// Assumes that the method returns a string
/// </summary>
/// <param name="assemblyName">name of the assembly containing the class in which the method lives.</param>
/// <param name="namespaceName">namespace of the class.</param>
/// <param name="typeName">name of the class in which the method lives.</param>
/// <param name="methodName">name of the method itself.</param>
/// <param name="stringParam">parameter passed to the method.</param>
/// <returns>the string returned by the called method.</returns>
///
public static string InvokeStringMethod5(string assemblyName, string namespaceName, string typeName, string methodName, string stringParam)
{
//This method was created incase Method has params with default values. If has params will return error and not find function
//This method will choice and is the preffered method for invoking
// Get the Type for the class
Type calledType = Type.GetType(String.Format("{0}.{1},{2}", namespaceName, typeName, assemblyName));
String s = null;
// Invoke the method itself. The string returned by the method winds up in s.
// Note that stringParam is passed via the last parameter of InvokeMember, as an array of Objects.
if (MethodHasParams(assemblyName, namespaceName, typeName, methodName))
{
s = (String)calledType.InvokeMember(
methodName,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
null,
null,
new Object[] { stringParam });
}
else
{
s = (String)calledType.InvokeMember(
methodName,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
null,
null,
null);
}
// Return the string that was returned by the called method.
return s;
}
public static bool MethodHasParams(string assemblyName, string namespaceName, string typeName, string methodName)
{
bool HasParams;
string name = String.Format("{0}.{1},{2}", namespaceName, typeName, assemblyName);
Type calledType = Type.GetType(name);
MethodInfo methodInfo = calledType.GetMethod(methodName);
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length > 0)
{
HasParams = true;
}
else
{
HasParams = false;
}
return HasParams;
}
//
///调用静态公共方法。
///假设该方法返回一个字符串
///
///包含方法所在类的程序集的名称。
///类的命名空间。
///方法所在的类的名称。
///方法本身的名称。
///传递给方法的参数。
///被调用方法返回的字符串。
///
公共静态字符串InvokeStringMethod5(字符串汇编名称、字符串名称空间名称、字符串类型名称、字符串方法名称、字符串字符串参数)
{
//此方法是在方法具有默认值的参数的情况下创建的。如果具有参数,则将返回错误且找不到函数
//此方法将选择,并且是用于调用的首选方法
//获取类的类型
Type calledType=Type.GetType(String.Format(“{0}.{1},{2}”,namespaceName,typeName,assemblyName));
字符串s=null;
//调用方法本身。方法返回的字符串以s结尾。
//请注意,stringParam作为对象数组通过InvokeMember的最后一个参数传递。
if(MethodHasParams(assemblyName、namespaceName、typeName、methodName))
{
s=(字符串)calledType.InvokeMember(
方法名,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
无效的
无效的
新对象[]{stringParam});
}
其他的
{
s=(字符串)calledType.InvokeMember(
方法名,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
无效的
无效的
无效);
}
//返回被调用方法返回的字符串。
返回s;
}
公共静态bool MethodHasParams(string assemblyName、string namespaceName、string typeName、string methodName)
{
布尔哈斯帕拉斯;
string name=string.Format(“{0}.{1},{2}”,namespaceName,typeName,assemblyName);
类型calledType=Type.GetType(名称);
MethodInfo MethodInfo=calledType.GetMethod(methodName);
ParameterInfo[]parameters=methodInfo.GetParameters();
如果(parameters.Length>0)
{
HasParams=true;
}
其他的
{
HasParams=false;
}
返回HasParams;
}
这是一种形式
有没有其他/更好的方法来做到这一点
这项活动能成为将军吗。与使用动态
类似,可以在.Net 4.0中调用非静态方法
,以便返回类型可以独立
我从未在实际场景中使用过dynamic
关键字(仅阅读一些示例),以了解我仍然不知道的实际用法
在此方面的任何帮助/指导都将不胜感激
感谢回答您关于动态的问题;不,那不适合这里<当成员名(或操作)在编译时已知,但无法证明存在时(基本上是duck类型),代码>动态
非常有用。例如:
dynamic foo = GetSomeRandomObject();
foo.ThisShouldExist("abc");
这做了类似的事情,但用法不同。所以,是的,你只剩下反思。你所做的几乎是对的。我唯一可以更改的是获取MethodInfo
,并从那里开始工作-尽管如果您可以更改API以接受单个字符串assemblyQualifiedName
,这将更加方便和灵活。但也许:
public static string InvokeStringMethod5(string assemblyName,
string namespaceName, string typeName, string methodName, string stringParam)
{
string assemblyQualifiedName = string.Format("{0}.{1},{2}",
namespaceName, typeName, assemblyName);
Type calledType = Type.GetType(assemblyQualifiedName);
if(calledType == null) throw new InvalidOperationException(
assemblyQualifiedName + " not found");
MethodInfo method = calledType.GetMethod(methodName,
BindingFlags.Public | BindingFlags.Static);
switch (method.GetParameters().Length)
{
case 0:
return (string)method.Invoke(null, null);
case 1:
return (string)method.Invoke(null, new object[] { stringParam });
default:
throw new NotSupportedException(methodName
+ " must have 0 or 1 parameter only");
}
}
要回答如何将结果强制转换为泛型返回类型的问题,该方法如下所示:
public static T InvokeMethod<T>(string assemblyName, string namespaceName, string typeName, string methodName, string stringParam)
{
// instead of String s = null;
T methodResult = default(T);
// instead of s = (String)calledType.InvokeMember(...)
methodResult = (T)calledType.InvokeMember(...);
// return s;
return methodResult;
}
publicstatict InvokeMethod(stringassemblyName、stringnamespaceName、stringtypeName、stringmethodName、stringstringparam)
{
//而不是字符串s=null;
T methodResult=默认值(T);
//而不是s=(字符串)calledType.InvokeMember(…)
methodResult=(T)calledType.InvokeMember(…);
//返回s;
返回方法结果;
}
要让方法返回任何类型,可以返回对象
(反射库中的大多数方法都是这样做的)或使用泛型方法。@C.evenhui将泛型和reflection@MarcGravell我不是说应该使用反射调用泛型方法,但只需将结果强制转换为所需类型,然后再将其传递回调用方。我的印象是,dynamic
和generic
这两个术语在问题中混淆了。@C.Evenhuis在您的上述评论之后,我们如何创建一个泛型方法,将被调用对象返回的类型作为返回Member@adcool2007将其作为答案发布,因为它太大,无法发表评论。@MarkGravell将完成此功能也适用于非静态/公共功能??另外,如果返回类型保留为对象如何将其强制转换为非静态函数所需的类型???@adcool2007,则需要更改BindingFlags
以包含实例
,并且需要包含非空对象作为调用
的第一个参数,但本质上,是的,同样的代码也适用于非静态方法。对于“将其转换为所需类型”——这在很大程度上取决于上下文。我返回了字符串,因为您的示例就是这样做的。你能说得更具体一点吗?这是可行的,但实际上,inti=InvokeMethod(…)
vsinti=(int)InvokeMethod(…)
。我们所改变的只是括号有多尖。