2011-04-24 58 views
2

我有一個情況,我有一些類,每個類都處理一個令牌。他們都從一個基本處理程序類下降(簡化了一點,所以請原諒任何反編譯錯別字):如何聲明類型列表,並稍後實例化?

public abstract class TokenClassBase 
{ 
    public static bool HandlesTokenType(TokenKind AType) 
    { 
    return handledTokens.Contains(AType); 
    } 
    protected virtual void HandleToken(AToken) 
    { 
    } 
} 

public class TokenClass1 : TokenClassBase 
{ 
    public static new bool HandlesTokenType(TokenKind AKind) 
    { 
    return AKind == TokenKind.type1; 
    } 
    public override void HandleToken(AToken) 
    { 
    //do some work 
    } 

} 
// public class TokenClass2... etc 

我也有一個工人階級,我想存儲這些處理程序的列表,並後來實例化處理的一個處理令牌:

public class MyWorker 
{ 
    private List<Type> handlers; 
    public MyWorker() 
    { 
    handlers = new List<Type>; 
    handlers.Add(typeof(TokenClass1)); 
    handlers.Add(typeof(TokenClass2)); 
    //... etc 
    } 
    protected virtual void HandleToken(AToken) 
    { 
    foreach (TokenBaseClass handler in handlers) 
    { 
     if (handler.HandlesToken(AToken)) 
     { 
     instantiate(handler); 
     handler.HandleToken(AToken); 
     break; 
     } 
    } 
    } 
} 

我的問題是,我該如何處理最後的foreach?這甚至是可能的 - 還是有更好的方法?我喜歡將來可以添加新類型的擴展性,只需將它們添加到處理程序列表(或者甚至從外部傳遞它們)即可。 我正在使用C#,框架3.5+。

回答

6

這是不可能這樣的,沒有 - 因爲你的列表是類型,不引用到情況下該類型的列表。

,你可以很容易地來最接近的,假設有一個爲每個類型參數的構造函數,方法是:

foreach (Type handlerType in handlers) 
{ 
    // Create an instance of the handler type 
    TokenBaseClass handler = 
     (TokenBaseClass) Activator.CreateInstance(handlerType); 
    if (handler.HandlesToken(AToken)) 
    { 
    handler.HandleToken(AToken); 
    break; 
    } 
} 

編輯:在回答在評論你的問題,我會略有不同處理這個問題。

我會將您的List<Type>更改爲List<Func<TokenKind, TokenClassBase>>。換句話說,工廠功能列表,從TokenKindTokenClassBase。每種類型的功能將取決於類型,但它會要麼返回TokenClassBasenull實例如果TokenKind無法處理。

然後你會使用:

foreach (var handlerFactory in handlerFactories) 
{ 
    TokenBaseClass handler = handlerFactory(AToken); 
    if (handler != null) 
    { 
     handler.HandleToken(AToken); 
     break; 
    } 
} 

,你需要創建代表將取決於你的代碼的確切性質的方式,但你既可以使用lambda表達式或方法組轉換,可能來自靜態方法。

+0

你也可以讓處理程序實現ICloneable(如果你想根據'serivce請求'克隆一個實例) – sehe 2011-04-24 19:31:42

+0

@sehe:是的,但你仍然需要一個實例列表,而不是一個類型列表。 – 2011-04-24 19:34:50

+0

啊哈,我誤解了你的評論,並且認爲這些類型已經被他們的實例存儲了。讀得太快了,斯里。仍然ICloneable環在這裏主題:) – sehe 2011-04-24 19:37:53

3

你可能想看看Activator.CreateInstance方法。

你的循環將

foreach (Type handlerType in handlers) 
{ 
    if (...not sure how you'd do this part...) 
    { 
    TokenBaseClass handler = (TokenBaseClass)Activator.CreateInstance(handlerType); 
    handler.HandleToken(AToken); 
    break; 
    } 
} 

對於缺少的部分,你基本上需要什麼令牌,每個類型可以處理一個列表。如果它是1-1關係,則可以考慮Dictionary<TokenKind,Type>。或者,爲了完全避免反射,請使用Dictionary<TokenKind,Func<TokenClassBase>>,每個值爲() => new TokenClass1()

爲什麼你想要一個類型列表而不是實例列表?