0

背景使用PropertyInfo

をジェネリックメソッドを呼び出すときに、私はEFを使用していると私は多くのテーブルを持っています。ナビゲーションプロパティのコンテンツを持つ新しいエンティティを挿入したときに、IDなしで(xlsファイルからコンテンツを読み込んでいます)、すべてのナビゲーションプロパティを明示的にロードしたくありません。これはあまりにも多くのコードでした。だから私は、一般的な方法を試してみました:

private void loadExistingNavigationProperties<TEntity>(TEntity entityToInsert) where TEntity : class 
{ 
    Type type = typeof(TEntity); 
    var properties = type.GetProperties().Except(type.GetProperties().Where(x => x.Name.Contains("id"))); 
    foreach (PropertyInfo property in properties) 
    { 
     if (property.PropertyType.FullName.Contains("MyNamespace")) 
     { 
      property.SetValue(entityToInsert, findNavigationProperty<???>(property.GetValue(entityToInsert))); 
     } 
    } 
} 

私は私のentityToInsertを持っています。ナビゲーションプロパティ(contains("MyNamespace"))がある場合は、そのプロパティをすべてチェックします。これが当てはまる場合は、ナビゲーションプロパティをロードし(下記参照)、設定する必要があります。

private object findNavigationProperty<TNavigationProperty>(TNavigationProperty navigationPropertyValue) where TNavigationProperty : class 
{ 
    List<TNavigationProperty> navigationProperties = GetAllEntries<TNavigationProperty>(); 
    foreach (var entity in navigationProperties) 
    { 
     if (propertiesAreEqual(entity, navigationPropertyValue)) 
     { 
      return entity; 
     } 
    } 
    return navigationPropertyValue; 
} 

ナビゲーションプロパティ属性の現在の値が渡されます。それは名前のようなすべての情報を含みますが、idは含みません。まず、そのタイプのすべての利用可能なナビゲーションプロパティを取得しています。次に、現在のプロパティと同じプロパティを持つプロパティがあるかどうかを調べています。次に、これが返され、ナビゲーションプロパティとして設定されます。

編集:

public List<TEntity> GetAllEntries<TEntity>() where TEntity : class 
{ 
    using (var dbContext = new InventarDBEntities(MainWindow.connectionName)) 
    { 
     return GetAllEntries<TEntity>(dbContext); 
    } 
} 

public List<TEntity> GetAllEntries<TEntity>(InventarDBEntities dbContext) where TEntity : class 
{ 
    return dbContext.Set<TEntity>().ToList(); 
} 

問題

私の問題は、今私はジェネリック型の型、プロパティの値が持っているという方法findNavigationPropertyを伝えることができる方法です。したがって、???をタイプに置き換えてください。

+1

実行時にジェネリック型を取得することはできません。汎用型は、コンパイル時に解決可能でなければなりません。実行時に解決された型をメソッドに渡す場合は、反映された 'System.Type'を渡すことでそれを行う必要があります。 'GetAllEntries()'は 'System.Type'のパラメータを受け入れるオーバーロードを持っていますか? –

+0

@NoelWidmer GetAllEntriesメソッドを追加しました。それはSystem.Typeのパラメータを受け付けません – L3n95

+0

あなたは 'InventarDBEntities'のソースも持っていますか?私はそれが.NETのタイプだと思います。その場合は、それが由来するクラス名の名前を教えてください。 (ジェネリック引数の代わりに 'System.Type'を受け入れる' InventarDBEntities.Set() 'オーバーロードがあるかどうか調べたいです) –

答えて

1

として:

var item = propertyInfo.GetGenericArguments()[0]; 

あなたはそれを使って、型であるかどうかを確認することができますが、あなたも行うことができます

「です」私はすでに私のコメントで述べた:
一般的な型の引数は、コンパイル時に解決されます。
したがって、System.Typeからジェネリックタイプを取得することはできません。

問題の鍵は、ジェネリックではなくSystem.Typeを使用することです。
EFをインストールしていないため、以下のコードはテストしていません。
私のkowledge DbContextのSystem.Typeオーバーロードはうまくいくはずです。

private void loadExistingNavigationProperties<TEntity>(TEntity entityToInsert) where TEntity : class 
{ 
    Type tEntity = typeof(TEntity); 
    var properties = tEntity.GetProperties().Except(tEntity.GetProperties().Where(x => x.Name.Contains("id"))); 
    foreach (PropertyInfo property in properties) 
    { 
     if (property.PropertyType.FullName.Contains("MyNamespace")) 
     { 
      object val = findNavigationProperty(property.GetValue(entityToInsert), tEntity); 
      property.SetValue(entityToInsert, val); 
     } 
    } 
} 

private object findNavigationProperty(object navigationPropertyValue, Type tEntity) 
{ 
    DbSet navigationProperties = GetAllEntries(tEntity); 
    foreach (var entity in navigationProperties) 
    { 
     // You may get a type issue. 
     // If so: cast to the correct type or change "propertiesAreEqual". 
     if (propertiesAreEqual(entity, navigationPropertyValue)) 
     { 
      return entity; 
     } 
    } 
    return navigationPropertyValue; 
} 

public DbSet GetAllEntries(Type tEntity) 
{ 
    using (var dbContext = new InventarDBEntities(MainWindow.connectionName)) 
    { 
     return GetAllEntries(dbContext, tEntity); 
    } 
} 

public DbSet GetAllEntries(InventarDBEntities dbContext, Type tEntity) 
{ 
    return dbContext.Set(tEntity); 
} 
+0

はい、動作します。それは、リフレクションを介してメソッドを呼び出すよりもはるかにクリーンです。ありがとうございました。私はちょうどDbSetがDbSet <>より少ないメソッドを持っている理由を理解できませんが、それは別の質問であり、キャストもこれを解決します。 – L3n95

+0

@ L3n95 Cool!私は非常に頻繁にDbSetを使用していないため、その質問に答えることはできません。私はいつもジェネリック型を一般的なオブジェクト型よりも好むでしょう。しかし、反射型を使用する場合は、通常、より良い選択肢はありません。 –

0

あなたはこのような一般的なタイプ取得することができます。

item.BaseType == typeof(Whatever type your navigation props inherit); 
関連する問題