Как превратить экземпляр типа в аргумент универсального типа

у меня в основном есть что-то вроде этого:

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

Foo(typeof(Person));

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

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

EDIT: я должен был упомянуть, что это надуманный пример. Я не могу фактически изменить подпись функции, потому что она реализует интерфейс.

EDIT: сериализатор-это JavascriptSerializer и реализован как фильтр действий здесь. Это называется так:

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

решение

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

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

5 ответов


Если 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 });

что сериализатор-это что? Если бы вы только знали 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);
}

использовать

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

со следующим вызовом

Foo<Person>();

в этом случае, просто сделать это:

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

Foo<Person>();

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


Как сказал Люцеро,

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

Foo<Person>();

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