C# 使用运行时类型执行的泛型方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1606966/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generic Method Executed with a runtime type
提问by Sarit
I have the following code:
我有以下代码:
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);
}
}
}
Now, I know I cannot perform DoSomething() is there any other way to use this function?
现在,我知道我无法执行 DoSomething() 有没有其他方法可以使用此功能?
采纳答案by Chris Patterson
You can, but it involves reflection, but you can do it.
你可以,但它涉及反思,但你可以做到。
typeof(ClassExample)
.GetMethod("DoSomething")
.MakeGenericMethod(p.DisplayType)
.Invoke(this, new object[] { p.Name, p.Value });
This will look at the top of the containing class, get the method info, create a generic method with the appropriate type, then you can call Invoke on it.
这将查看包含类的顶部,获取方法信息,创建具有适当类型的泛型方法,然后您可以对其调用 Invoke。
回答by Maximilian Mayerl
this.GetType().GetMethod("DoSomething").MakeGenericMethod(p.Value.GetType()).Invoke(this, new object[]{p.Name, p.Value});
Should work.
应该管用。
回答by SLaks
Generics types cannot be specified at runtime the way you'd like to here.
不能在运行时按照您希望的方式指定泛型类型。
The simplest options would be to add a non-generic overload of DoSomething
, or simply call DoSomething<object>
and ignore p.DisplayType
. Unless SendToDatabase
depends on the compile-timetype of value
(and it probably shouldn't), there should be nothing wrong with giving it an object
.
最简单的选择是添加 的非泛型重载DoSomething
,或者简单地调用DoSomething<object>
并忽略p.DisplayType
。除非SendToDatabase
依赖于(它可能不应该)的编译时类型,否则value
给它一个object
.
If you can't do those, you'll have to call DoSomething
using reflection, and you'll take a big performance hit.
如果你不能做到这些,你将不得不DoSomething
使用反射调用,并且你会受到很大的性能影响。
回答by elder_george
Strictly saying you can use MethodInfo.MakeGenericMethodfor this.
严格地说,您可以为此使用MethodInfo.MakeGenericMethod。
But I recommend to change DoSomething to non-generic form instead, since it is not evident whether it really should be generic.
但我建议将 DoSomething 改为非泛型形式,因为它是否真的应该是泛型尚不清楚。
回答by stevemegson
First we need to convert p.Value
to the right type, since even if we know the type at compile time we can't pass the string straight to the method...
首先我们需要转换p.Value
为正确的类型,因为即使我们在编译时知道类型,我们也不能将字符串直接传递给方法......
DoSomething<Int32>( "10" ); // Build error
For simple numeric types and DateTime, we can use
对于简单的数字类型和日期时间,我们可以使用
object convertedValue = Convert.ChangeType(p.Value, p.DisplayType);
Now we can use reflection to invoke the required generic method...
现在我们可以使用反射来调用所需的泛型方法...
typeof(ClassExample)
.GetMethod("DoSomething")
.MakeGenericMethod(p.DisplayType)
.Invoke(this, new object[] { p.Name, convertedValue });