Reflection + Linq + DbSet - PullRequest
       11

Reflection + Linq + DbSet

4 голосов
/ 06 июня 2011

Я использую код EF сначала 4.1. в моем приложении. Теперь я хочу получить сущности через сервисы WCF, используя универсальные типы. Я пытаюсь отразить универсальный тип и вызвать метод ToList из DbSet Object. Вот мой код:

 public string GetAllEntries(string objectType)
        {
            try
            {
             var   mdc =
                   Globals.DbConnection.Create(@"some_db_connection", true);

               // Getting assembly for types
                var asob = Assembly.GetAssembly(typeof(CrmObject));
               // getting requested object type from assembly
                var genericType = asob.GetType(objectType, true, true);

                if (genericType.BaseType == typeof(CrmObject))
                {
                    // Getting Set<T> method
                    var method = mdc.GetType().GetMember("Set").Cast<MethodInfo>().Where(x => x.IsGenericMethodDefinition).FirstOrDefault();

                   // Making Set<SomeRealCrmObject>() method
                    var genericMethod = method.MakeGenericMethod(genericType);
                   // invoking Setmethod into invokeSet 
                    var invokeSet = genericMethod.Invoke(mdc, null);
                   // invoking ToList method from Set<> invokeSet 
                    var invokeToList = invokeSet.GetType().GetMember("ToList").Cast<MethodInfo>().FirstOrDefault();

                    //this return not referenced object as result
                    return invokeToList.ToString();
                }

                return null;
            }
            catch (Exception ex)
            {
                return ex.Message + Environment.NewLine + ex.StackTrace;
            }
        }

На самом деле тогда я пишу код, как return mdc.Set<SomeRealCrmObject>().ToList() - у меня отлично работает! Но затем я использую универсальные типы, которые не могу найти метод ToList в объекте DbSet<SomeRealCrmObject>().

Ответы [ 3 ]

7 голосов
/ 07 июня 2011

Eranga правильно, но это более простое использование:

dynamic invokeSet = genericMethod.Invoke(mdc, null);
var list = Enumerable.ToList(invokeSet);

C # 4 dynamic позаботится о громоздком родовом отражении для вас.

4 голосов
/ 06 июня 2011

ToLIst () не является членом DbSet / ObjectSet, но является методом расширения.

Вы можете попробовать это вместо

var method = typeof(Enumerable).GetMethod("ToList");
var generic = method.MakeGenericMethod(genericType);
generic.Invoke(invokeSet, null);
0 голосов
/ 09 июня 2016

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

Мне нужно было вызвать свойство DbSet для DbContext на основе универсального типа для DbSet.Так, например, тип может называться County, а свойство DbSet называется Counties.Приведенный ниже метод загрузки будет загружать объекты типа T (округ) и возвращать массив объектов T (список объектов округов), вызывая свойство DbSet с именем Counties.EntityList - это просто объект-декоратор, который берет список элементов поиска и добавляет дополнительные свойства, необходимые для сетки на внешнем интерфейсе.

    public T[] Load<T>() where T : class
    {
        var dbProperty = typeof(Data.BmpDB).GetProperties().FirstOrDefault(
            x => x.GetMethod.ReturnType.GenericTypeArguments[0].FullName == typeof(T).FullName);

        if (dbProperty == null)
            return null;

        dynamic data = dbProperty.GetMethod.Invoke(BmpDb, null);
        var list = Enumerable.ToList(data) as List<T>;
        var entityList = new Data.EntityList<T>(list);

        return entityList.Results;
    }
...