通用方法中执行一个运行时类型
我有以下代码:通用方法中执行一个运行时类型
public class ClassExample
{
void DoSomthing<T>(string name, T value)
{
SendToDatabase(name, value);
}
public class ParameterType
{
public readonly string Name;
public readonly Type DisplayType;
public readonly string Value;
public ParameterType(string name, Type type, string value)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
if (type == null)
throw new ArgumentNullException("type");
this.Name = name;
this.DisplayType = type;
this.Value = value;
}
}
public void GetTypes()
{
List<ParameterType> l = report.GetParameterTypes();
foreach (ParameterType p in l)
{
DoSomthing<p.DisplayType>(p.Name, (p.DisplayType)p.Value);
}
}
}
现在,我知道我不能执行DoSomething的() 有没有使用此功能的任何其他方式?
你可以,但它涉及反思,但你可以做到。
typeof(ClassExample)
.GetMethod("DoSomething")
.MakeGenericMethod(p.DisplayType)
.Invoke(this, new object[] { p.Name, p.Value });
这将着眼于包含类的顶部,获得方法的信息,创建具有相应类型的通用方法,那么你可以调用来调用它。
this.GetType().GetMethod("DoSomething").MakeGenericMethod(p.Value.GetType()).Invoke(this, new object[]{p.Name, p.Value});
应该工作。
无法在运行时按照您希望的方式指定泛型类型。
最简单的选择是添加DoSomething
的非通用超载,或者只需调用DoSomething<object>
并忽略p.DisplayType
。除非SendToDatabase
取决于编译时间类型的value
(它可能不应该),那么给它一个object
应该没有问题。
如果你不能做到这些,你将不得不使用反射来调用DoSomething
,并且你将获得巨大的性能。
严格地说你可以使用MethodInfo.MakeGenericMethod这个。
但我建议将DoSomething改为非泛型形式,因为它不是真的应该是通用的。
我只是简化了解释程序。这实际上是最优雅的解决方案,信不信由你。 :) 谢谢! – Sarit 2009-10-22 12:57:36
首先,我们需要p.Value
转换为正确的类型,因为即使我们知道在编译时的类型,我们不能将字符串传递直奔方法...
DoSomething<Int32>("10"); // Build error
对于简单的数字类型和日期时间,我们可以使用
object convertedValue = Convert.ChangeType(p.Value, p.DisplayType);
现在我们可以使用反射来调用所需的通用方法...
typeof(ClassExample)
.GetMethod("DoSomething")
.MakeGenericMethod(p.DisplayType)
.Invoke(this, new object[] { p.Name, convertedValue });
只有一个catch,p.Value是一个字符串,所以调用将失败,除非p.DisplayType碰巧是typeof(string)。 – stevemegson 2009-10-22 13:39:57
惭愧这是唯一的解决方案,meh – 2009-11-16 21:54:58
嗯,我想你可以在4.0中使用动态,它会推断正确的泛型参数类型,但我还没有机会验证它。并不是说它在封面上做的和上面的代码不同,但也许是这样。 – 2009-11-16 22:11:11