【问题标题】:Reflection + Linq + DbSet反射 + Linq + DbSet
【发布时间】:2011-09-09 07:53:15
【问题描述】:

我使用 EF 代码优先 4.1。在我的应用程序中。现在我想使用泛型类型通过 WCF 服务获取实体。 我试图反映泛型类型并调用 DbSet 对象的方法 ToList。 这是我的代码:

 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&lt;SomeRealCrmObject&gt;().ToList() 之类的代码——对我来说很好用!但是后来我使用了泛型类型,我在对象DbSet&lt;SomeRealCrmObject&gt;() 中找不到方法 ToList。

【问题讨论】:

    标签: linq reflection entity-framework-4.1 ef-code-first


    【解决方案1】:

    Eranga 是正确的,但这是更简单的用法:

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

    C# 4 的 dynamic 为您处理繁琐的通用反射。

    【讨论】:

      【解决方案2】:

      ToLIst() 不是 DbSet/ObjectSet 的成员,而是扩展方法。

      你可以试试这个

      var method = typeof(Enumerable).GetMethod("ToList");
      var generic = method.MakeGenericMethod(genericType);
      generic.Invoke(invokeSet, null);
      

      【讨论】:

      • 一个小细节是 ToList 是一个静态扩展方法 - 因此它必须像这样调用:generic.Invoke(null, new [] { invokeSet });。这是因为静态方法不是从实例调用的——如果方法是静态的,则 Invoke 的第一个参数将被忽略。此外,由于这是一个扩展方法,它的第一个参数必须是要转换为列表的集合。
      【解决方案3】:

      我遇到了类似的情况,我需要一种方法来动态加载用于页面上搜索条件的下拉列表的值,从而允许用户对给定的表运行即席查询。我想动态地执行此操作,以便在添加新字段时不会在前端或后端更改代码。所以使用动态类型和一些基本反射,它解决了我的问题。

      我需要做的是基于 DbSet 的泛型类型在 DbContext 上调用 DbSet 属性。例如,该类型可能称为 County,而 DbSet 属性称为 Counties。下面的加载方法将加载类型为 T(县)的对象,并通过调用名为 Counties 的 DbSet 属性返回一个 T 对象数组(县对象列表)。 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;
          }
      

      【讨论】:

        猜你喜欢
        • 2021-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-07
        • 1970-01-01
        • 2020-09-29
        相关资源
        最近更新 更多