为方法调用动态设置类型
Set type dynamically for method call
我有一个静态函数:
public static MyCollection<T> Parse<T>(string? json) where T : BaseClass
{
...
}
而且效果很好。它根据类型在内部做出决定并生成正确的集合。
但是,我想要的集合基于来自另一个来源的文件名,我希望有一个集合并动态设置类型,如:
Type t;
if (name == "Certain name") t = typeof(CertainChildClassOfBaseClass);
if (name == "Other name") t = typeof(OtherChildClassOfBaseClass);
var myCollection = ParsingService.Parse<t>(jsonString);
这显然行不通,但我正在尝试的可能吗?我真的不想写一堆内容几乎相同的 if/else 块,这样每个块都可以有不同的类型(我已经在 Parse
函数中编写了那些特定于类型的块 - 做同样的分支两次似乎我犯了一个更根本的错误)。我愿意接受有关如何以“正确”方式执行此操作的建议。也许我必须通过反思来做到这一点,这并没有让我兴奋,但这并不是世界末日。一个可能的问题是我的解析服务是静态的。
乐于助人。
通常,我会建议使 Parse
非泛型,然后进行泛型重载:
public static MyCollection<BaseClass> Parse(Type type, string? json)
{
...
}
public static MyCollection<T> Parse<T>(string? json) where T : BaseClass
{
return (MyCollection<T>)Parse(typeof(T), json);
}
但是你不能使 MyCollection
逆变,因为它是一个具体的 class,因此强制转换是非法的。而且无论如何,逆变容器使用起来很危险(例如,看看数组)。
另一种方法是使用反射来获取所需方法的版本(称为“关闭”泛型类型的过程):
var genericMethod = typeof(/* class containing Parse */).GetMethod("Parse");
var method = genericMethod.MakeGenericMethod(type); // type will be substituted for your 'T', above
object collection = method.Invoke(json); // call the method
在这里我们遇到了另一个障碍:collection
的类型将是 object
,您需要将其转换为其他类型。但是你不能使用 MyCollection<T>
因为你不知道 T
,你不能使用 MyCollection<BaseClass>
因为,好吧,又没有逆变。
所以真正的主要障碍是 MyCollection
类型。只要是那样,您就没有简单的方法可以绕过它。您可以改为 return 一个非泛型集合,例如 ICollection
或 IList
,但这样您就失去了类型安全性,您将不得不在以后继续转换。这完全取决于你。
我有一个静态函数:
public static MyCollection<T> Parse<T>(string? json) where T : BaseClass
{
...
}
而且效果很好。它根据类型在内部做出决定并生成正确的集合。
但是,我想要的集合基于来自另一个来源的文件名,我希望有一个集合并动态设置类型,如:
Type t;
if (name == "Certain name") t = typeof(CertainChildClassOfBaseClass);
if (name == "Other name") t = typeof(OtherChildClassOfBaseClass);
var myCollection = ParsingService.Parse<t>(jsonString);
这显然行不通,但我正在尝试的可能吗?我真的不想写一堆内容几乎相同的 if/else 块,这样每个块都可以有不同的类型(我已经在 Parse
函数中编写了那些特定于类型的块 - 做同样的分支两次似乎我犯了一个更根本的错误)。我愿意接受有关如何以“正确”方式执行此操作的建议。也许我必须通过反思来做到这一点,这并没有让我兴奋,但这并不是世界末日。一个可能的问题是我的解析服务是静态的。
乐于助人。
通常,我会建议使 Parse
非泛型,然后进行泛型重载:
public static MyCollection<BaseClass> Parse(Type type, string? json)
{
...
}
public static MyCollection<T> Parse<T>(string? json) where T : BaseClass
{
return (MyCollection<T>)Parse(typeof(T), json);
}
但是你不能使 MyCollection
逆变,因为它是一个具体的 class,因此强制转换是非法的。而且无论如何,逆变容器使用起来很危险(例如,看看数组)。
另一种方法是使用反射来获取所需方法的版本(称为“关闭”泛型类型的过程):
var genericMethod = typeof(/* class containing Parse */).GetMethod("Parse");
var method = genericMethod.MakeGenericMethod(type); // type will be substituted for your 'T', above
object collection = method.Invoke(json); // call the method
在这里我们遇到了另一个障碍:collection
的类型将是 object
,您需要将其转换为其他类型。但是你不能使用 MyCollection<T>
因为你不知道 T
,你不能使用 MyCollection<BaseClass>
因为,好吧,又没有逆变。
所以真正的主要障碍是 MyCollection
类型。只要是那样,您就没有简单的方法可以绕过它。您可以改为 return 一个非泛型集合,例如 ICollection
或 IList
,但这样您就失去了类型安全性,您将不得不在以后继续转换。这完全取决于你。