2012-12-26 201 views
4

我可以使用反射類型作爲類型參數嗎?例如。我想根據通過的對象選擇一個持卡人:我可以使用反射類型作爲類型參數嗎?

IPersister GetPersisterFor(IEntity entity) 
{ 
    return GetPersisterFor<entity.GetType()>(); // <-- this cannot be compiled 
} 

IPersister GetPersisterFor<TEntity>() where TEntity : IEntity 
{ 
    //some logic to get persister... 
} 

回答

4

只能通過反射;你需要使用GetMethod來獲得MethodInfo的通用方法,然後在MakeGenericMethod(entity.GetType()).Invoke(this, null);上調用。

然而,更容易是經由動態欺騙:

IPersister Evil<T>(T obj) where T : IEntity { 
    return GetPersisterFor<T>(); 
} 

並作出公正的第一種方法:

return Evil((dynamic)entity); 

這是再一個動態表達這將檢測校正t使用(以召喚邪惡的T)給你。

注意:您需要額外方法的唯一原因是要確保它不會遞歸解析回自身,因爲名稱是相同的。

+0

任何你爲什麼稱它爲惡的原因? :) –

+0

@Rhys,因爲我需要把它叫做:) –

+0

+1或者,你可以在調用樹上向泛型類型參數'T'推。在某種程度上,「實體」的確切類型可能是已知的,所以如果從這一點到「GetPersisterFor」的所有方法都將「T」保留爲泛型類型,則不需要使用「動態」。如果這是不可能的(頂層調用者只有一個'IYo'類型的變量可用),那麼這是'MakeGenericMethod'解決方案的一個很好的捷徑。 – jam40jeff

1

是的,你需要獲得泛型方法的定義。 之後,您可以使用MethodInfo.MakeGenericMethod構建通用方法。

所以喜歡的東西:

MethodInfo genericMethodDefinition = GetType() 
    .GetMethods(BindingFlags.Instance | BindingFlags.NonPublic) 
    .Where(method => method.IsGenericMethod && method.Name == "GetPersisterFor") 
    .First(); 

// OR 

MethodInfo genericMethodDefinition = GetType().GetMethod("GetPersisterFor", 
    BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null); 

// THEN 

MethodInfo genericMethod = genericMethodDefinition.MakeGenericMethod(entity.GetType()); 
genericMethod.Invoke(this, null); 
+0

在GetMethod中,您需要更多一點:訪問非公共方法,以及b:在相同的泛型方法和非泛型方法之間消除歧義名字 –

+0

@MarcGravell,謝謝。 –

1

由於通用和非通用的方法有相同的名字,你必須遍歷類的所有方法找到合適的一個,然後調用它:

public IPersister GetPersisterFor(IEntity entity) 
{  
    MethodInfo getPersisterForGenericMethod = 
        GetType().GetMethods() 
         // iterate over all methods to find proper generic implementation 
         .Single(methodInfo => methodInfo.Name == "GetPersisterFor" && methodInfo.IsGenericMethod) 
         // supply it with generic type parameter 
         .MakeGenericMethod(entity.GetType()); 

    // invoke it 
    return getPersisterForGenericMethod.Invoke(this, null) as IPersister; 
} 

public IPersister GetPersisterFor<TEntity>() where TEntity : IEntity 
{ 
    return null; 
} 

ps:完整的源代碼可在gist.github

相關問題