X is a variable but used like a type when trying to cast

亡梦爱人 提交于 2019-11-27 19:32:16

问题


I am passing a string of the name of the entity type I want to query and getting the type based on the string. I want to get the DbSet back and return an IQueryable. The problem is where I am doing (DbSet<tableEntity>) and getting the following error:

tableEntity is a variable but used like a type

when trying to cast. Is there a way to resolve this?

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();            
}

EDIT

Just to add I don't have access to the type that's we I am passing the name through a string.


回答1:


So it turns out that the entity type is literally not known, or knowable, at compile time. It has to be a string.

The only place you're using the type at compile time is in the cast to (DbSet<tableEntity>). Well, you may not need that. All you need from that type is to call AsQueryable(), and AsQueryable() is an extension method for IEnumerable, with generic and non-generic versions. IF we call it through non-generic IEnumerable, that's non-generic AsQueryable(), returning non-generic IQueryable. But we're returning object anyway, so hey. For the result of this thing to be useful, something somewhere must be doing a fair amount of reflection on it anyway, so the declared type is likely to be of little consequence.

See if this works:

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();            
}

If it turns out you need generic IQueryable<TEntityType>, we'll have to use reflection to get MethodInfo for AsQueryable<TEntityType> for the unknown (at compile time) entity type, and call MakeGenericMethod(tableEntity) on that.


First try:

In the language, type parameters to generics must be actual types, not instances of the Type class. That's because they're resolved at compile time.

But that's no problem; to pass a type parameter to a generic method, simply write a generic method with a type parameter.

You can't do this:

var stuff = GetList("MyTableEntityClass");

But this is just as good:

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();            
}

Reflection is different; that's why we pass typeof(TTableEntity) to MakeGenericMethod().

And once we're using an actual type that the compiler can check, we can do better with our return type, too:

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

    return dbObject.AsQueryable();            
}



回答2:


Since, as Ed mentioned, you don't use the table entity type at compile time, why not just use the non-generic databaseContext.Set (tableEntity).AsQueryable ()? But if you've set your heart on Set<>, try this:

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();            
}


来源:https://stackoverflow.com/questions/44207451/x-is-a-variable-but-used-like-a-type-when-trying-to-cast

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!