[英]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.