基于运行时值获取泛型类型的字典

Get a dictionary of a generic type based on a runtime value

提问人:Zenith 提问时间:11/8/2023 最后编辑:Zenith 更新时间:11/8/2023 访问量:158

问:

我希望声明一个基于运行时类型的字典。所以,与其这样做:

IEnumerable dict = null;
if(type == typeof(SomeType)) dict = new Dictionary<SomeType, string>()
if(type == typeof(SomeOtherType)) dict = new Dictionary<SomeOtherType, string>()

我想做这样的事情:

IEnumerable dict = new Dictionary<type, string>();

我怎样才能做到这一点?此外,我希望能够通过以下方式之一仅使用字典类型调用不同的方法:

var result = SomeMethod(typeof(Dictionary<type, string>));
var result = SomeMethod<Dictionary<type, string>>();

编辑: 额外上下文:

我从不同的 API 调用中获取类型作为字符串。然后,我使用反射通过 AssemblyQualifiedName 获取类型,从而生成一个用于执行调用的 List。根据这些类型的名称,需要调用 REST 端点。

If (type == SomeType) httpClient.GetAsync("SomePath/{SomeType.Name}")

此终结点返回 Dictionary<SomeType, string>。为了能够反序列化这些类型,我需要调用类似的东西

httpClient.GetAsync<Dictionary<type, string>>("SomePath/{SomeType.Name}")

否则,System.Text.Json 包中将发生异常。

C# .NET 类型 反射

评论

1赞 shingo 11/8/2023
为什么不能使用?Dictionary<object, string>
0赞 Zenith 11/8/2023
@shingo我正在使用 ,但需要对 HttpClient 和反序列化做一些事情,这需要硬类型才能正确地反序列化到该字典中。Dictionary<InterfaceThatAllRelevantTypesImplement, string>
0赞 Jon Skeet 11/8/2023
创建后,在编译时绝对不需要强类型方式吗?(如果您能在问题中提供更多背景信息,那将非常有帮助。
0赞 jmcilhinney 11/8/2023
“我怎样才能做到这一点?”你不能。这不是泛型的工作方式。您需要在编译时知道泛型类型参数。如果不这样做,编译器怎么可能保证类型安全?
1赞 Jon Skeet 11/8/2023
@jmcilhinney:如果你不需要这种安全,那也没关系。看看我的答案。问题中实际要求的所有内容都可以很容易地完成。这是否真的足以满足OP的要求是另一回事。

答:

6赞 Jon Skeet 11/8/2023 #1

如果你真的不关心编译时的类型,你只想创建一个实例,你可以用反射轻松做到这一点:

var dictionaryType = typeof(Dictionary<,>).MakeGenericType(type, typeof(string));
var dictionary = Activator.CreateInstance(dictionaryType);

上面的构造还可以让你调用:dictionaryType

var result = SomeMethod(dictionaryType);

评论

0赞 Zenith 11/8/2023
这似乎正是我想要的。谢谢!我仍然在反序列化方面存在一些问题,但至少正确使用了该类型。关于将 json 反序列化为运行时类型字典的任何提示?
2赞 Jon Skeet 11/8/2023
@StijnWingens:不,请提出一个包含所有相关背景的新问题。(我甚至不知道你的意思,即使很清楚,在评论中提出后续问题也是不合适的。