2017-05-26 10 views
2

私は問合せしたい文字列に基づいて型を取得するエンティティ型の名前の文字列を渡します。私はDbSetを返し、IQueryableを返したいと思います。キャストしようとしたときXは変数ですが、キャストしようとしたときに型のように使用されます

tableEntity is a variable but used like a type

:私は(DbSet<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();    
} 

EDIT

+0

:あなたはSet<>にあなたの心を設定した場合でも、これを試してみてください!あなたがそれを落とさない限り、あなたは常にこのような厄介なことに足を踏み入れます。 [コンパイラに関するイントロを読む](https://meta.stackexchange.com/questions/25840/can-we-stop-recommending-the-dragon-book-please)これはあなたが専門的に働いているツールです。それが原則的にどのように機能するかを知っていなければならない。 –

+0

DBがMS Sql Serverであるか、同じデータ型定義(https://stackoverflow.com/a/28561947/4228193)を使用している場合は、次のような便利な機能があります。すべての場所のSystem.Web。私は以下のように使います。 'TypeCode systc = Parameter.ConvertDbTypeToTypeCode([SqlMetaData_instance] .DbType); try { 返信Convert.ChangeType(val、systc); } ' – mpag

答えて

4

したがって、コンパイル時にエンティティタイプが文字通り知られていない、またはわかっていることが判明しました。それは文字列でなければなりません。

コンパイル時にタイプを使用している唯一の場所は、キャスト内で(DbSet<tableEntity>)です。まあ、必要ないかもしれません。そのタイプから必要なのは、AsQueryable()を呼び出すことです。AsQueryable()は、IEnumerableの拡張メソッドで、汎用バージョンと非汎用バージョンです。非汎用のIEnumerableで呼び出すと、非汎用のAsQueryable()となり、非汎用のIQueryableが返されます。しかし、とにかくobjectを返しているので、ねえ。このことが有用であるという結果を得るには、とにかくどこかに何かが反映されなければならないので、宣言された型はほとんど影響を受けません。

これが動作するかどうかを参照してください:それはあなたが一般的なIQueryable<TEntityType>を必要と判明した場合、我々は未知の(コンパイル時に)エンティティタイプのためAsQueryable<TEntityType>ためMethodInfoを取得するためにリフレクションを使用する必要があります

public object GetList(string tableEntity) 
{ 
    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();    
} 

、およびコールそれに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();    
} 
+0

このソリューションの問題は、私はこのタイプにアクセスする必要がないか、そうしたことです。私が今いる状況は、BALがEntity Frameworkオブジェクトを取得するためにDALを通過しなければならないということです。申し訳ありませんが私の質問に追加する必要があります。 – Kogroth

+0

@Kogrothああ私のゴリ、これは信じられないほど簡単かもしれない。 –

+0

@Kogroth更新を参照してください。そのことが分かれば教えてください。 –

0

、エドが述べたように、あなたがテーブルを使用していませんコンパイル時にエンティティタイプを使用すると、非汎用のdatabaseContext.Set (tableEntity).AsQueryable()を使用しないのはなぜですか?コンパイル時と実行時との差が非常に重要である

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();    
} 
関連する問題