OK,问题的范围转移,但我原来的观察和反对一些其他的解决方案仍然有效。
我认为你不想在这里使用'泛型'。您不会提前知道类型,因为您需要创建类型,所以不需要使用通用实现,因为MethodBase.Invoke需要一个Object数组。
此代码假定您正在从数据库字段实例化目标。如果不是相应调整。
当然这不是全部包含的,也没有有用的异常处理,但它可以让你动态地执行任意类型的任意方法,任意类型的参数值都来自一行中的字符串值。
注意:有许多许多情况下,这个简单的执行程序将无法正常工作。您需要确保您设计动态方法,以配合您最终决定使用的任何策略。
using System;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.Reflection;
using NUnit.Framework;
namespace DynamicMethodInvocation
{
[TestFixture]
public class Tests
{
[Test]
public void Test()
{
// from your database
string assemblyQualifiedTypeName = "DynamicMethodInvocation.TestType, DynamicMethodInvocation";
string methodName = "DoSomething";
// this is how you would get the strings to put in your database
string enumString = Executor.ConvertToString(typeof(AttributeTargets), AttributeTargets.Assembly);
string colorString = Executor.ConvertToString(typeof(Color), Color.Red);
string stringString = "Hmm... String?";
object result = Executor.ExecuteMethod(assemblyQualifiedTypeName, methodName,
new[] { enumString, colorString, stringString });
Assert.IsInstanceOf<bool>(result);
Assert.IsTrue((bool)result);
}
}
public class TestType
{
public bool DoSomething(AttributeTargets @enum, Color color, string @string)
{
return true;
}
}
public class Executor
{
public static object ExecuteMethod(string assemblyQualifiedTypeName, string methodName,
string[] parameterValueStrings)
{
Type targetType = Type.GetType(assemblyQualifiedTypeName);
MethodBase method = targetType.GetMethod(methodName);
ParameterInfo[] pInfo = method.GetParameters();
var parameterValues = new object[parameterValueStrings.Length];
for (int i = 0; i < pInfo.Length; i++)
{
parameterValues[i] = ConvertFromString(pInfo[i].ParameterType, parameterValueStrings[i]);
}
// assumes you are instantiating the target from db and that it has a parameterless constructor
// otherwise, if the target is already known to you and instantiated, just use it...
return method.Invoke(Activator.CreateInstance(targetType), parameterValues);
}
public static string ConvertToString(Type type, object val)
{
if (val is string)
{
return (string) val;
}
TypeConverter tc = TypeDescriptor.GetConverter(type);
if (tc == null)
{
throw new Exception(type.Name + " is not convertable to string");
}
return tc.ConvertToString(null, CultureInfo.InvariantCulture, val);
}
public static object ConvertFromString(Type type, string val)
{
TypeConverter tc = TypeDescriptor.GetConverter(type);
if (tc == null)
{
throw new Exception(type.Name + " is not convertable.");
}
if (!tc.IsValid(val))
{
throw new Exception(type.Name + " is not convertable from " + val);
}
return tc.ConvertFrom(null, CultureInfo.InvariantCulture, val);
}
}
}
我认为你正在寻找的字'动态'而不是'一般'。当您的需求描述需要从描述性字符串动态创建参数值时,您已经获得了许多有关此用法的解答。我是否正确地理解你? – 2010-03-03 17:15:16
我对所有人回答的其他问题是:在回答之前没有人完全阅读和理解问题吗? Jeez .... – 2010-03-03 17:16:33
好的,下一个问题:你在调用什么方法?调度方法已知的现有实例化对象,还是您正在实例化目标? – 2010-03-03 17:44:45