将混凝土浇筑到基础通用抽象类

时间:2018-05-26 13:58:31

标签: c# generics

我有一个通用的基础抽象类:

public abstract class Generator<T>
{
    public abstract void Start(T config);
}

然后,我有许多从基类继承的具体类,并期望某些参数类型。其中一些:

public class AGenerator : Generator<AGeneratorConfig>
{
    public override void Start(AGeneratorConfig Config) { /* some code*/ }
}

public class BGenerator : Generator<BGeneratorConfig>
{
    public override void Start(BGeneratorConfig Config) { /* some code*/ }
}

他们的Start()方法参数定义如下:

public abstract class GeneratorConfig
{
    public int CommonProperty {get; set;}
}

public class AGeneratorConfig : GeneratorConfig
{
    // Some props specific for AGenerator
}

public class BGeneratorConfig : GeneratorConfig
{
    // Some props specific for BGenerator       
}

最后,我有一个客户端/经理/工厂类,用提供的配置处理实际的生成器启动过程, 但是使用铸造混凝土来抽象泛类:

public class GeneratorClient
{
    public static void StartGenerator<T>(T config)
    {
        Generator<T> generator = null;

        if (config is AGeneratorConfig)
        {
            generator = new AGenerator() as Generator<T>; // casting to abstract base class
        }
        else if (config is BGeneratorConfig)
        {
            generator = new BGenerator() as Generator<T>; // casting to abstract base class
        }
        else
        {
            throw new NotImplementedException();
        }

        generator.Start(config);
    }
}

我的问题:是否有任何解决方法可以消除将具体方法转换为抽象基类的需要?

最简单的解决方案是:

public static void StartGenerator<T>(T config)
{
    if (config is AGeneratorConfig)
    {
        var generator = new AGenerator();
        generator.Start(config);
    }
    else if (config is BGeneratorConfig)
    {
        var generator = new BGenerator();
        generator.Start(config);
    }
    else
    {
        throw new NotImplementedException();
    }
}

但是对于每个新创建的具体生成器,对象generator.Start(config);需要重复。

2 个答案:

答案 0 :(得分:2)

generator定义为object,并仅在最后一次通话时将其投放到Generator<T>

public static void StartGenerator<T>(T config)
{
    object generator = null;

    if (config is AGeneratorConfig)
    {
        generator = new AGenerator();
    }
    else if (config is BGeneratorConfig)
    {
        generator = new BGenerator();
    }
    else
    {
        throw new NotImplementedException();
    }

    ((Generator<T>)generator).Start(config);
}

答案 1 :(得分:1)

您可以使用Reflection来调用构造函数,也可以改进Factory,以便删除那些if。

您可以使用这样的词典:

    private Dictionary<Type, Type> Diccionary;
    public void CreateDicionary()
    {
        Diccionary = new Dictionary<Type, Type>();
        Diccionary.Add(typeof(AGeneratorConfig), typeof(AGenerator));
        Diccionary.Add(typeof(BGeneratorConfig), typeof(BGenerator));
    }

然后你可以使用这样的具体实例:

   public Generator<T> GetGenerator<T>()
    {
        var type = typeof(T);
        if (!Diccionary.ContainsKey(type))
            throw new Exception("Not found");

        var typeInstance = Diccionary[type];

        return (Generator<T>) Activator.CreateInstance(typeInstance);
    }

您使用上面的代码与此类似:

 public  void StartGenerator<T>(T config)
    {
        var generator = GetGenerator<T>();
        generator.Start(config);
    }


    public static void Main()
    {
        var gen = new GeneratorClient();
        gen.CreateDicionary();
        gen.StartGenerator<AGeneratorConfig>(new AGeneratorConfig());
    }