繁体   English   中英

将混凝土浇筑到基础通用抽象类的解决方法

[英]Workaround for casting concrete to base generic abstract class

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

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       
}

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

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对象generator.Start(config); 需要重复。

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);
}

您可以使用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());
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM