X是一个变量,但在尝试投射时像一个类型一样使用

时间:2017-05-26 17:46:41

标签: c# reflection types dbset

我传递了一个我要查询的实体类型名称的字符串,并根据字符串获取类型。我希望返回DbSet并返回IQueryable。问题是我正在做(DbSet<tableEntity>)并收到以下错误:

  

tableEntity是一个变量,但像类型一样使用

试图施法时。有办法解决这个问题吗?

public object GetList(string tableEntity)
{
    Type tableEntity = Type.GetType("TestProject." + typeName + ", TestProject");

    var dbObject = (DbSet<tableEntity>)typeof(DbContext).GetMethod("Set", Type.EmptyTypes)
                        .MakeGenericMethod(tableEntity)
                        .Invoke(databaseContext, null);

    return dbObject.AsQueryable();            
}

修改

只是要添加我无法访问我们通过字符串传递名称的类型。

2 个答案:

答案 0 :(得分:5)

因此事实证明,在编译时,实体类型在字面上是未知的或可知的。它必须是一个字符串。

您在编译时使用该类型的唯一位置是转换为(DbSet<tableEntity>)。好吧,你可能不需要那个。您只需拨打AsQueryable()AsQueryable()就是IEnumerable的扩展方法,具有通用和非通用版本。如果我们通过非通用IEnumerable调用它,那就是非通用AsQueryable(),返回非通用IQueryable。但是我们无论如何都要回归object,所以嘿。为了使这个东西变得有用,某些东西必须在它上面进行相当多的反思,所以声明的类型可能没那么重要。

看看是否有效:

public object GetList(string typeName)
{
    Type tableEntity = Type.GetType("TestProject." + typeName + ", TestProject");

    var dbObject = (System.Collections.IEnumerable)
                        typeof(DbContext).GetMethod("Set", Type.EmptyTypes)
                        .MakeGenericMethod(tableEntity)
                        .Invoke(databaseContext, null);

    return dbObject.AsQueryable();            
}

如果事实证明您需要通用IQueryable<TEntityType>,那么我们必须使用反射为MethodInfo获取AsQueryable<TEntityType>未知(在编译时)实体类型,并且就此致电MakeGenericMethod(tableEntity)

首先尝试:

在该语言中,对泛型的类型参数必须是实际类型,而不是Type类的实例。这是因为它们在编译时已经解决了。

但那没问题;要将类型参数传递给泛型方法,只需使用类型参数编写泛型方法即可。

你不能这样做:

var stuff = GetList("MyTableEntityClass");

但这也很好:

var stuff = GetList<MyTableEntityClass>();

...

public object GetList<TTableEntity>()
{
    var dbObject = (DbSet<TTableEntity>)typeof(DbContext)
                        .GetMethod("Set", Type.EmptyTypes)
                        .MakeGenericMethod(typeof(TTableEntity))
                        .Invoke(databaseContext, null);

    return dbObject.AsQueryable();            
}

反思不同;这就是我们将typeof(TTableEntity)传递给MakeGenericMethod()的原因。

一旦我们使用了编译器可以检查的实际类型,我们也可以使用返回类型做得更好:

public IQueryable<TTableEntity> GetList<TTableEntity>()
{
    var dbObject = (DbSet<TTableEntity>)typeof(DbContext)
                        .GetMethod("Set", Type.EmptyTypes)
                        .MakeGenericMethod(typeof(TTableEntity))
                        .Invoke(databaseContext, null);

    return dbObject.AsQueryable();            
}

答案 1 :(得分:1)

因为,正如Ed所说,你不在编译时使用表实体类型,为什么不使用非泛型databaseContext.Set (tableEntity).AsQueryable ()?但是,如果你已经放心Set<>,请试试这个:

public object GetList(string tableEntity)
{
    Type tableEntity = Type.GetType("TestProject." + typeName + ", TestProject");

    return GetType ()
        .GetMethod ("GetListHelper")
        .MakeGenericMethod (tableEntity)
        .Invoke    (this) ;
}

public object GetListHelper<T> () where T : class
{
    var dbObject = databaseContext.Set<T> (null) ;
    return dbObject.AsQueryable();            
}