[英]Workaround for casting concrete to base generic abstract class
I have a generic base abstract class: 我有一个通用的基础抽象类:
public abstract class Generator<T>
{
public abstract void Start(T config);
}
Then, I have many concrete classes that inherit from base class and expect certain parameter type. 然后,我有许多从基类继承并期望某些参数类型的具体类。 Some of them:
他们中的几个:
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*/ }
}
Their Start()
method parameters are defined as follows: 他们的
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
}
At last, I have a client/manager/factory-like class that handles actual generator start process with provided config, but is uses casting concrete to abstract generic class: 最后,我有一个客户端/经理/工厂类,使用提供的配置处理实际的生成器启动过程,但是使用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);
}
}
My question: is there any workaround to eliminate the need of casting concrete to abstract base classes? 我的问题:是否有任何解决方法可以消除将抽象混凝土浇筑到抽象基类的需要?
The most simple solution would be this: 最简单的解决方案是:
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();
}
}
but for each newly created concrete Generator object generator.Start(config);
但是对于每个新创建的具体Generator对象
generator.Start(config);
needs to be repeated. 需要重复。
Define the generator
just as object
and cast it to Generator<T>
only at the last call: 将
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);
}
You can use Reflection to call the constructor, and maybe improve you Factory in order to remove those if's. 您可以使用Reflection来调用构造函数,也可以改进Factory,以便删除那些if。
You can use a dictionary like this: 你可以使用这样的字典:
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));
}
then you can have the concrete instance with something like this: 那么你可以用这样的东西得到具体的实例:
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);
}
And you use the code above with something similar to this: 并且您使用上面的代码与此类似的东西:
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.