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

本文关键字:列表 类型 实例化 然后 一个 声明 何声明 | 更新日期: 2023-09-27 17:53:14

我有一个例子,我有一些类,每个类处理一种类型的令牌。它们都是从基处理程序类派生的(简化了一点,所以请原谅任何反编译的拼写错误):

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+。

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

这是不可能的,因为您的列表是类型的列表,而不是对该类型的实例的引用。

假设每个类型都有一个无参数的构造函数,最接近的情况是:

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。每种类型的函数取决于类型,但如果不能处理TokenKind,则返回TokenClassBase null的实例。

那么你可以使用:

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

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

您可能需要查看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()

为什么你想要一个类型列表而不是实例列表呢?