2016-12-30 90 views
1

功能我有以下簽名的extesion方法傳遞參數通過反射

public static void AddConfiguration<TEntity>(this ModelBuilder builder, EntityTypeConfiguration<TEntity> configuration) 
    where TEntity : class 
{ 
    ... 
} 

我想通過通過反射的參數,並嘗試這種方法:

var ctors = type.GetConstructors(BindingFlags.Public); 
modelBuilder.AddConfiguration(ctors[0].Invoke(new object[] { })); 

而且這種方式:

modelBuilder.AddConfiguration(Activator.CreateInstance(type)); 

我從反射得到的類是這樣的:

public class LessonMapping : EntityTypeConfiguration<Lesson> 
public class ChapterMapping : EntityTypeConfiguration<Chapter> 
public class TrainingMapping : EntityTypeConfiguration<Training> 

兩者都返回一個object,所以該方法不接受它們。有沒有辦法做到這一點?

+0

你要投Activator.CreateInstance' – BradleyDotNET

+0

是的'的結果,但我得到通過反射的類型和它有一個通用的'TEntity'所以我不知道該怎麼做 – RBasniak

+0

的是創建對象一個'TEntity'? – InBetween

回答

2

Activator有一個創建具有默認構造函數的類型化實例的通用方法。通過它的外觀你有,那麼使用以下命令:

var obj = Activator.CreateInstance<LessonMapping>(); 
modelBuilder.AddConfiguration(obj); 

如果不適合你,或者你需要傳遞參數給你的構造:最後,如果你是

var obj = (LessonMapping)Activator.CreateInstance(typeof(LessonMapping)); 
modelBuilder.AddConfiguration(obj); 

把這個代碼內的另一個通用方法,你能有一個通用的替代LessonMapping等:

void DoSomethingGeneric<TEntity>(ModelBuilder builder) 
{ 
    var obj = Activator.CreateInstance<EntityTypeConfiguration<TEntity>>(); 
    modelBuilder.AddConfiguration(obj); 
} 

編輯AddConfigurati的加反思在方法

爲了您AddConfiguration的方法的非通用用法,你將不得不使用反射來調用它:

void DoSomethingNonGeneric(ModelBuilder builder, Type entityType) 
{ 
    // make the generic type for the given entity type using the generic definition 
    var entityConfigType = typeof(EntityTypeConfiguration<>).MakeGenericType(new Type[] { entityType }); 

    // instantiate the entity type configuration 
    var obj = Activator.CreateInstance(entityConfigType); 

    // get and make a generic method to invoke with the object above. Check the binding flags if it doesn't find the method 
    var methodDef = typeof(Extensions).GetMethod("AddConfiguration", BindingFlags.Static | BindingFlags.Public); 
    var method = methodDef.MakeGenericMethod(new Type[] { entityConfigType }); 

    // and finally the end goal 
    method.Invoke(null, new object[] { builder, obj }); 
} 

我在這一點上的假設是:

  1. 要傳遞實體的類型(而不是配置)。如果您要傳遞配置類的類型,請將參數名稱entityType更改爲entityConfigType,並刪除生成泛型類型的第一行。請參閱下面的類型檢查代碼,以替代第一行。
  2. 您的擴展方法在名爲Extensions的類中。
  3. 您正在檢查類型是否符合AddConfiguration(...)的要求,因此您不會因使用錯誤的類型而獲得調用異常。下面再看看我通常會添加到這種非泛型方法的類型檢查示例。
  4. 設置methodDef的行按預期工作,因爲我目前無法測試它。

如果直接傳遞entityConfigType並要檢查的類型,然後在第幾行補充一點:

if (!CheckDerivesFrom(typeof(EntityTypeConfiguration<>), entityConfigType) 
    throw new ArgumentException("entityConfigType"); 

而且某處創建檢查方法。我確定必須有一種更簡單的方法來測試一個類型是否來自給定的泛型定義,但我一直使用它,直到我看到更簡單的方式。

bool CheckDerivesFrom(Type baseType, Type typeToCheck) 
{ 
    if (!baseType.IsGenericDefinition) 
     return baseType.IsAssignableFrom(typeToCheck); 

    // assume typeToCheck is never a generic definition 
    while (typeToCheck != null && typeToCheck != typeof(object)) 
    { 
     if (typeToCheck.IsGenericType && baseType.IsAssignableFrom(typeToCheck.GetGenericDefinition())) 
      return true; 
     typeToCheck = typeToCheck.BaseType; 
    } 
    return false; 
} 
+0

我通過反射來獲取它們,因爲我有50個映射類,並且手動保持'AddConfiguration'代碼同步不合適,這就是爲什麼我試圖通過反射來完成它。你的解決方案會起作用,但是我必須手動將對象轉換爲類型,所以我最終會以同樣的方式處理50個調用。現在我看到,我應該把這個背景放在問題上,以更好地描述真正的問題。 – RBasniak

+0

好吧,那麼你真正想要的是通過反射來執行配置方法,我會更新我的答案 – strongbutgood

+0

謝謝,didn' t工作,我想通過配置,所以我做了你指出的變化,並且在Invoke調用中出現以下錯誤:''SORTE.Persistence.Mappings.ChapterMapping'無法轉換爲'SORTE'類型。 Persistence.EntityTypeConfiguration'1',但用反射調用方法本身的想法很好。我會盡力從這裏出發 – RBasniak