C# 如何将typeName字符串转换为泛型?

C# 如何将typeName字符串转换为泛型?,c#,asp.net,asp.net-mvc,asp.net-mvc-3,generics,C#,Asp.net,Asp.net Mvc,Asp.net Mvc 3,Generics,这个问题的背景是一个MVC应用程序,它接受字符串,并希望将其转换为类型,然后将其转换为通用代码 我有一个输入类型的字符串表示 对于泛型方法,我似乎从未在中放入类型变量 这是否意味着我必须手动列出所有可能的情况和通用方法调用?这样做对吗 如果一个ModelBinder能够以某种方式找出一个类型,我可以为一个动作方法public ActionResult Something()提供一个泛型类型参数,那就太酷了。但我不知道这是否可能 范例 public ActionResult DoSomethi

这个问题的背景是一个MVC应用程序,它接受字符串,并希望将其转换为类型,然后将其转换为通用代码

  • 我有一个输入类型的字符串表示
  • 对于泛型方法,我似乎从未在
    中放入
    类型
    变量
  • 这是否意味着我必须手动列出所有可能的情况和通用方法调用?这样做对吗
  • 如果一个
    ModelBinder
    能够以某种方式找出一个类型,我可以为一个动作方法
    public ActionResult Something()
    提供一个泛型类型参数,那就太酷了。但我不知道这是否可能
范例

public ActionResult DoSomething(string typeName, int? id)
{
    var type = Type.GetType(typeName);
    if (type == typeof(Apple)) DoSomethingElse<Apple>(id);
    if (type == typeof(Orange)) DoSomethingElse<Orange>(id);
    //if etc ... to infinity
}
public ActionResult DoSomething(字符串类型名,int?id)
{
var type=type.GetType(typeName);
if(type==typeof(Apple))DoSomethingElse(id);
if(type==typeof(Orange))DoSomethingElse(id);
//如果等…到无穷远
}

如果只有该类型,则必须通过反射将其全部保存。假设“DoSomethingElse”是当前类中的一个方法:

public ActionResult DoSomething(string typeName, int? id)
{
    Type thisType = this.GetType(); // Get your current class type
    var type = Type.GetType(typeName);
    MethodInfo doSomethingElseInfo = thisType.GetMethod("DoSomethingElse");
    MethodInfo concreteDoSomethingElse = doSomethingElseInfo.MakeGenericMethod(type);
    concreteDoSomething.Invoke(this, null);
}

这应该对你有用,尽管你应该注意,它不会很漂亮

因为它是一个控制器方法,所以您不是真正调用
DoSomething
的人,因此无法将类型分配给该方法,例如:

public ActionResult DoSomething<T>(int? id)
public ActionResult DoSomething(int?id)

因为调用该方法的是IIS,所以您没有任何方式来分配此类型。现在我并不完全了解路由,所以路由可能是可行的,但对我来说似乎不太可能。看起来您正在使用enum,所以也许可以使用enum.Parse来实例化或创建int的扩展方法,该方法能够根据类型确定int。

反射和泛型不是好朋友。DozsomethingElse真的需要通用吗?如果它只是把一个类型作为一个参数,那就容易多了…@marcgravel,我不知道。我的印象是,使用泛型比到处传递类型更枯燥、更通用。也许这是一个错误的印象。我个人对泛型的绑定工作很感兴趣。但是如果泛型没有提供我想象中的好处,我也会感兴趣。泛型在编译时使用它们时会提供这些好处。当在运行时动态使用它们时,它们会更加麻烦。例如,MakeGenericMethod有一个性能开销。他没有要求更改“DoSomething”方法。他在问如何使用泛型/反射来调用泛型方法,而不提前知道要传递给泛型方法的类型?id将只是实体框架处理的数据库id。@Vijay:请阅读他最后一条bullet语句。这正是他所要求的。如何通过使用泛型避免反射。要在这种情况下使用泛型,他必须修改签名。@Benjamin:在控制器的上下文中,
int?id
是通过url作为可选参数输入的变量。它可能反映了数据库中的某个id,但OP显然有一些类型可以转换为(re:enum)。@JoelEtherton我错了,我把你的回复作为道歉投了赞成票;)你是说这里的代码不漂亮,还是说会出现其他复杂情况?@Benjamin抱歉,我的意思是你不应该真的这样编写代码。你不应该使用反射来让某些东西正常工作。您想要的方式无法实现,因为直到运行时才知道对象的类型,而DoSomethingElse的类型参数必须在编译时知道。编译器不可能分辨出要将调用解析到哪个DoSomethingElse,因此这是非法的。如果您使用接口/基类,您可以在不提前知道对象类型的情况下调用对象上的方法,但是泛型在这方面不是您的朋友…我不喜欢使用反射。这很费时,而且很糟糕。我更喜欢您的解决方案:“var type=type.GetType(typeName);if(type==typeof(Apple))DoSomethingElse(id);”我知道这似乎是一种代码味道,但这就是以这种方式使用泛型的成本。您可以始终将该方法放在对象中(虽然不是非常MVVM:-S)并使用基/接口调用调用该方法,但这会破坏您的模式。像这样调用这个方法没有什么害处,只是我不会选择这样做。我随时都会接受额外的打字;)好的,谢谢,我会尝试一下,这样我就不会把所有额外的输入都留给自己:)@Benjamin你说得对,只需要对方法编写一次代码,但是(在本例中)成本将是你必须编写的大型if/else或case语句。如果你在网上发布你的DoSomethingElse代码和你正在使用的类型(pastebin?),那么我会看一看,看看是否能找到其他方法为你做到这一点!