Как превратить экземпляр Type в аргумент универсального типа - PullRequest
9 голосов
/ 13 мая 2009

У меня в принципе есть что-то вроде этого:

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

Foo(typeof(Person));

Deserialize<ty> не работает, потому что вместо этого ожидается Deserialize<Person>. Как мне обойти это?

Я также хотел бы понять, как работают дженерики и почему он не принимает ty, что typeof(Person).

РЕДАКТИРОВАТЬ: Я должен был упомянуть, что это надуманный пример. Я не могу изменить сигнатуру функции, потому что она реализует интерфейс.

РЕДАКТИРОВАТЬ: сериализатор является JavascriptSerializer и реализован здесь как фильтр действий. Это называется так:

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

Решение

На основании ответов Марка и Антона:

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

Ответы [ 5 ]

7 голосов
/ 13 мая 2009

Какой это сериализатор? Если вы знаете 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);
}
6 голосов
/ 13 мая 2009

Если 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 голосов
/ 13 мая 2009

Используйте

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

Со следующим звонком

Foo<Person>();
1 голос
/ 13 мая 2009

Как сказал Лусеро,

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

Foo<Person>();

typeof (Person) - это не то же самое, что Person. Person - это тип времени компиляции, тогда как typeof (Person) - это выражение, которое возвращает экземпляр типа, представляющий информацию о типе среды выполнения Person .

.
1 голос
/ 13 мая 2009

В этом случае просто сделайте это:

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

Foo<Person>();

В противном случае вам необходимо вызывать обобщенный метод с поздним связыванием, так как вы должны сначала получить правильный обобщенный метод для него (он не известен во время компиляции). Взгляните на метод MethodInfo.MakeGenericMethod .

...