如何将一个类型实例转换为泛型类型参数

10

我基本上有这样的东西:

void Foo(Type ty)
{
    var result = serializer.Deserialize<ty>(inputContent);
}

Foo(typeof(Person));
Deserialize<ty>无法工作,因为它需要Deserialize<Person>。我该如何解决这个问题?我也想了解泛型是如何工作的,以及为什么它不接受typeof(Person)ty参数。

编辑:我应该提到这只是一个人为的例子。我无法更改函数的签名,因为它实现了一个接口。

编辑:serializer是JavascriptSerializer,并在此处作为操作筛选器实现。它被这样调用:

[JsonFilter(Param="test", JsonDataType=typeof(Person))]

解决方案

基于 Marc 和 Anton 的答案:

var result = typeof(JavaScriptSerializer).GetMethod("Deserialize")
                 .MakeGenericMethod(JsonDataType)
                 .Invoke(serializer, new object[] { inputContent });

肯定比寻找解决方法更容易,改变接口(或添加新的Foo重载)而不是在正确的代码如此简单时寻找解决方法? - stevehipwell
5个回答

7

这是哪种序列化器?如果你只在运行时(而不是编译时)知道 Type,并且它没有非泛型 API,则可能需要使用 MakeGenericMethod

void Foo(Type ty)
{
    object result = typeof(ContainingClass).GetMethod("Bar").
        .MakeGenericMethod(ty).Invoke(null, new object[] {inputContent});
}
public static T Bar<T>(SomeType inputContent) {
    return serializer.Deserialize<T>(inputContent);
}

我不确定这里的ContainingClass是什么,为什么要传入“Bar”? - aleemb
ContainingClass是具有Bar方法的类,而“Bar”用于按名称查找Bar方法。您还可以(根据Anton的答案)直接转到序列化程序上的“Serialize”方法。 - Marc Gravell
现在明白了。这个代码可行:var result = typeof(JavaScriptSerializer).GetMethod("Deserialize") .MakeGenericMethod(JsonDataType).Invoke(serializer, new object[] { inputContent }); 调用 Invoke(null, ...) 会抛出一个 TargetException 异常("需要非静态方法")。 - aleemb

6
如果在编译时已知 `ty`,为什么不直接这样做呢?
void Foo<T>()
{
    var result = serializer.Deserialize<T>(inputContext);
}

否则,
MethodInfo genericDeserializeMethod = serializer.GetType().GetMethod("Deserialize");
MethodInfo closedDeserializeMethod = genericDeserializeMethod.MakeGenericMethod(ty);
closedDeserializeMethod.Invoke(serializer, new object[] { inputContext });

2

使用

void Foo<T>(){ var result = serializer.Deserialize<T>(inputContent); }

通过以下调用

Foo<Person>();

1
在这种情况下,只需这样做:
void Foo<ty>()
{
    var result = serializer.Deserialize<ty>(inputContent);
}

Foo<Person>();

否则,您需要调用晚期绑定的通用方法,因为您首先必须获取正确的通用方法(在编译时未知)。请查看MethodInfo.MakeGenericMethod方法。

1

就像Lucero所说的那样,

void Foo<ty>()
{
    var result = serializer.Deserialize<ty>(inputContent);
}

Foo<Person>();

typeof(Person) 不同于 Person。Person 是编译时类型,而 typeof(Person) 是一个表达式,返回表示 Person 运行时类型信息的 Type 实例


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接