Универсальный метод типа ‹T› во время выполнения И сохранение результата в IEnumerable ‹T›

Прежде чем пометить его как дубликат, обратите внимание, что я прочитал все эти вопросы, включая ответ Джона Скита, но у меня все еще есть проблема. Ссылки, которые я просмотрел, и еще несколько, которые я здесь не перечисляю:

Создать экземпляр объекта с отражением и подсчетом динамических аргументов

Указание универсальному типу возвращать объект динамического тип

Есть ли способ не использовать динамический при создании экземпляра типа, наследуемого от универсального?

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

В основном я хочу это сделать:

public IEnumerable<T> GetListing<T>(string entityName)
{
    Entity entity = new Entity { Name = entityName, Action = "Select" };

    ResponsePacket<T> entityViewModel = new ResponsePacket<T>();

    entityViewModel.Records = myHttpClient.GetAllEntities<T>(entity, "10", "0").Content;

    return entityViewModel.Records.AsEnumerable();
}

И назовите это так:

public IEnumerable<myType> CallListing(string entityName)
{
    Type myType = {get type of entityName through some method eg User}
    IEnumerable<myType> result = GetListing<myType>;
    return result;
}

СЕЙЧАС я прочитал, что это невозможно достичь без отражения, что означает, что мне нужно создать экземпляр GetListing<>, а затем сообщить ему через отражение о <T>.

Моя проблема в том, что даже если я использую отражение для создания экземпляра GetListing<myType> и вызываю его во время выполнения через отражение, Как мне получить возвращенный результат GetListing<T> в IEnumerable<myType>? Будет ли отражение также предоставит результат IEnumerable<myType> в время выполнения?

Насколько мне известно, возвращенный результат Reflection является объектом. Как мне преобразовать его в IEnumerable<myType>, я не могу преобразовать его в IList следующим образом:

IList returnedresult = (IList)returnedResult, потому что моей странице сетки / представления нужна модель IEnumerable<myType> то есть IEnumerable<User> ИЛИ IEnumerable<Roles>, которую я надеюсь получить с помощью отражения. Я должен передать модель своему представлению @model IEnumerable<GridModel>, где для gridmodel потребуется IEnumerable<myType>.

Я также читал, что здесь можно использовать динамический, но я не знаю, как это сделать. Как мне достичь того, что я ищу, используя динамику? Я понятия не имею. Скажите, пожалуйста, есть ли способ сохранить возвращенный результат отраженного метода в IEnumerable<myType>.

Если и то и другое не может быть достигнуто, скажите, пожалуйста, как я могу добиться этого другим способом.

Я не знаю Тип объекта во время компиляции, иначе будет много репликации кода, и если у меня есть 100 объектов, для которых я хочу вызвать GetListing (), мне пришлось бы написать GetUserListing, GetRolesListing, Get ... Listing ( ), а затем мне пришлось бы явно вызвать GetListing<User>, GetListing<Roles> из методов GetUserListing, GetRolesListing, что противоречит цели.


person zeppelin    schedule 30.05.2014    source источник
comment
моей странице Grid / View требуется модель IEnumerable ‹* Type› Почему это? Если вы не знаете тип во время компиляции, какие преимущества дает страница от наличия универсального IEnumerable?   -  person Ben Aaronson    schedule 30.05.2014
comment
IEnumerable ‹myType›, то есть IEnumerable ‹User› или IEnumerable ‹Roles›, который я бы получил через отраженный возвращенный результат, если я смогу сохранить его в IEnumerable ‹myType›.   -  person zeppelin    schedule 30.05.2014
comment
Можете ли вы определить Тип от entityName до вызова CallListing?   -  person    schedule 30.05.2014
comment
@zeppelin Верно, у меня вопрос: зачем вам в конечном итоге IEnumerable<User>, а не просто IEnumerable, если вы не знаете, что тип будет User во время компиляции?   -  person Ben Aaronson    schedule 30.05.2014
comment
Что вы имеете в виду под тренировкой? Я надеюсь получить тип объекта через строку, entityName = User или Role будет предоставлен пользователем во время выполнения. Например, я получу User, затем я попытаюсь преобразовать строку User в Type User. Этот тип будет сохранен в переменной myType, тип данных которой будет Type. Затем я хочу передать это GetListing ‹myType›.   -  person zeppelin    schedule 30.05.2014
comment
@BenAaronson My View должен быть строго типизирован с помощью ‹entity›, чтобы сетка могла автоматически генерировать столбцы на основе ‹entity›, т.е. если он получает ‹User›, он будет генерировать столбцы для модели пользователя и так далее.   -  person zeppelin    schedule 30.05.2014
comment
Возможно, я неправильно понимаю суть проблемы, но постараюсь уточнить - откуда entityName? Можете ли вы сделать эту часть Type myType= {get type of entityName through some method eg User} дальше по стеку, а затем сделать CallListing универсальным и просто передать параметр универсального типа?   -  person    schedule 30.05.2014
comment
@DaveParsons entityName - это строка, которая будет предоставлена ​​пользователем во время выполнения. Если entityName = User, я сделаю это Type User, используя отражение. Тип myType = User также может быть передан в CallListing в качестве параметра, но он будет извлечен из предоставленной пользователем строки посредством отражения.   -  person zeppelin    schedule 30.05.2014
comment
@zeppelin А, так это ограничение наложено сторонним кодом? Это довольно раздражает. Думали ли вы о том, что все, что не является универсальным, вплоть до момента, когда вы передадите свою модель представлению, и только после этого использовать отражение для получения универсального IEnumerable<MyType>?   -  person Ben Aaronson    schedule 30.05.2014
comment
Если я правильно вас понял, не использовать общий язык - значит писать отдельные методы листинга для каждого типа сущности? Я думаю, что это противоречит цели того, к чему я здесь стремлюсь. Прямо сейчас у меня есть отдельный метод, такой как GetUserListing, GetRoleListing и т. Д. Весь код внутри этих методов такой же, за исключением типа объекта. Я хочу создать один метод, который будет делать то же самое для разных типов сущностей, которые будут предоставляться во время выполнения.   -  person zeppelin    schedule 30.05.2014
comment
Но вам все равно понадобятся отдельные методы CallListing?   -  person Zache    schedule 30.05.2014
comment
Нет, CallListing получит только entityName, изменит строку entityName на Type, сохранит ее в переменной myType, а затем вызовет GetListing ‹* myType›. CallListing ничего не делает, а просто преобразует строку entityName в Type и предоставляет myType в GetListing в качестве универсального параметра между угловыми скобками.   -  person zeppelin    schedule 30.05.2014


Ответы (1)


Я думаю, это то, что вам нужно:

void Main()
{
    Console.WriteLine(Get<int>("System.Int32").ToString());
    Console.WriteLine(Get<string>("System.String").ToString());
    Console.WriteLine(Get<double>().ToString());
    Console.WriteLine(Get<long>().ToString());
}

public Type TypeResolver(string type)
{
    return Type.GetType(type);
}

public IEnumerable<T> Get<T>(string typeName)
{   
    var type = TypeResolver(typeName);
    var entityStore = new EntityStore();
    return entityStore.GetType().GetMethod("GetAll").MakeGenericMethod(type).Invoke(entityStore, null) as IEnumerable<T>;
}

public IEnumerable<T> Get<T>()
{
    var entityStore = new EntityStore();
    return entityStore.GetType().GetMethod("GetAll").MakeGenericMethod(typeof(T)).Invoke(entityStore, null) as IEnumerable<T>;
}

public class EntityStore
{
    public IEnumerable<T> GetAll<T>()
    {
        return new List<T>();
    }
}
person Zache    schedule 30.05.2014
comment
В вашем методе Main () вы передаете ‹int›, ‹string› ‹double› во время компиляции, и соответствующий метод GetAll () вызывается на основе этих типов, но в моей проблеме я не знаю типы, например, если У меня есть пользователь, которому я хочу позвонить Get ‹User›. Я думаю, что в вашем примере Get ‹int›, Get ‹string› - это то же самое, что писать GetListing ‹User› или GetListing ‹Roles›, что невозможно, потому что я не знаю тип во время компиляции. В противном случае было бы слишком много операторов switch case, в которых мне пришлось бы перечислять все возможные типы, которые могут быть вызваны. - person zeppelin; 31.05.2014
comment
if (entityName == User) {Console.WriteLine (Get ‹User› (Models.User) .ToString ());} else if (...) {Console.WriteLine (Get ‹Roles› (Models.Roles). ToString ());} else if (..) {...} else if (...) {Get ‹..›}. Это означало бы, что мне пришлось бы перечислить каждую подобную модель, я не хочу этого делать, я не знаю тип во время компиляции. - person zeppelin; 31.05.2014
comment
Это просто показало вам, что это работает. Попробуйте код, прежде чем вы скажете, что он не работает. - person Zache; 03.06.2014
comment
На самом деле я потратил некоторое время, прежде чем ответить на ваше сообщение, потому что я сам хотел попробовать ваш код, я попробовал его, а затем ответил здесь. Пожалуйста, прочтите мои комментарии выше и скажите, если я неправильно понял данный код, потому что я, честно говоря, не знаю, я пробовал, пожалуйста, прочтите мои два вышеупомянутых комментария и скажите мне, где я ошибаюсь. - person zeppelin; 05.06.2014
comment
Тогда то, о чем вы просите, невозможно. C # не выполняет динамическую отправку методов, вам нужно знать, какая перегрузка метода вызывается при компиляции. Это включает в себя дженерики. То, что вы обычно не видите часть ‹T› в Visual Studio, не означает, что ее там нет. - person Zache; 09.06.2014