如何声明类型列表,稍后实例化一个?

Geo*_*off 2 c# types reference class list

我有一个案例,我有一些类,每个类处理一种令牌.它们都来自一个基本处理程序类(简化了一下,所以请原谅任何反编译错别字):

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
Run Code Online (Sandbox Code Playgroud)

我还有一个worker类,我想存储这些处理程序的列表,然后实例化其中一个处理程序来处理一个令牌:

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;
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,我如何处理最后的foreach?这甚至可能 - 还是有更好的方法?我喜欢将来能够添加新类型的可扩展性,只需将它们添加到处理程序列表中(或者甚至从外部传递它们).我正在使用c#,框架3.5+.

Jon*_*eet 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;
   }
}
Run Code Online (Sandbox Code Playgroud)

编辑:在评论中回答你的问题,我会稍微区别对待.

我会改变你List<Type>List<Func<TokenKind, TokenClassBase>>.换句话说,工厂的功能列表,从TokenKindTokenClassBase.每种类型的功能将取决于类型,但它要么返回的实例TokenClassBase,或者 null如果TokenKind无法处理.

那你就用了:

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

您创建委托的方式取决于代码的确切性质,但您可以使用lambda表达式或方法组转换,可能来自静态方法.