我正在使用一个通用的工厂类,其中通用零件是正在使用的派生类。正常用法很明显:BaseClass<DerivedA> C = new BaseClass<DerivedA>().
现在尽管我试图将财产注入放入我使用这些类的班级中。为此,我试图将类型作为参数(以便我可以使用派生的类别(。
现在,尽管我寻找例子并在自己身边尝试,但我有些亏损。我现在想知道:根本可以使用这种结构吗?如果是这样,我该如何实例化和使用,并且存在?
存在?用法:
public class MyMainClass
{
object _ClassInstance; // BaseClass<DerivedA> or BaseClass<DerivedB>
public MyyMainClass(Type typeIWant)
{
.....
}
}
....
MyMainClass a = new MyMainClass(typeof(DerivedA));
MyMainClass b = new MyMainClass(typeof(DerivedB));
通用类:
public abstract class BaseClass<T> where T: BaseClass<T>, new()
{
...
public bool Exists(int a) {...}
}
派生类:
public class DerivedA :BaseClass<DerivedA>
{
...
}
public class DerivedB :BaseClass<DerivedB>
{
...
public bool ExistsB(string a) {...}
}
您可以创建一个通过此操作的任何类型的实例:
_ClassInstance = Activator.CreateInstance(typeIWant)
不建议这样做,因为您将永远检查其类型并在要使用一种基本方法之一时施放它。如果您能够更改主类以进行类型参数,则应该像这样:
public class MyMainClass<T> where T: BaseClass<T>, new()
{
T _ClassInstance; // BaseClass<DerivedA> or BaseClass<DerivedB>
public MyMainClass()
{
_ClassInstance = new T();
}
}
这将允许您使用Baseclass上定义的任何方法。鉴于您要使用"不存在",这不是,您仍然需要在运行时检查其类型并施放它。我会推荐这样的东西:
if (_ClassInstance is DerivedB derivedB)
derivedB.ExistsB("...");
如果您确实需要编译时间检查,我建议您的课程需要更改。您无法仅访问派生类上定义的方法或属性,仅参考基础类。
这是您想要的吗?
Object instance1 = Activator.CreateInstance<Object>();
Object instance2 = Activator.CreateInstance(typeof(object));
我建议您使用getType
使用类型名称。如果您升级继承(从派生b等继承了另一个类(,如果您使用getType
,则可以确保仅适用于派生类型的实例调用此方法。
MyMainClass b = new MyMainClass(typeof(DerivedB));
if(b.GetType() == typeof(DerivedB))
b.ExistsB(...);
这是抽象类的主要问题 - 您共享接口和实现。但是就您而言,您强烈依赖不同的界面。要简化问题,只需查看您实际想要的东西:
public interface IExistable<in TValue>
{
bool Exists(TValue value);
}
public interface IDerivedA : IExistable<int>
{
}
public interface IDerivedB : IExistable<int>, IExistable<string>
{
}
您可以看到,您用两个接口使IDERIVEDB过度复杂化,也就是说,您的主级在某些情况下取决于IDERIVEDB。扩展接口还不错,您只是使用它错误。因此,您必须做的是为主级定义接口:
public interface IMainClass
{
//some methods here
}
创建两个实现:
public class ConcreteMainClass : CommonMainClass //you can derive from common, delegate to inner instance or implement interface from scratch - you decide depending on situation
{
private readonly IDerivedB _instance;
public ConcreteMainClass(IDerivedB instance) : base(instance)
{
_instance = instance;
}
//you can override some logic here depending on IExistable<string> from IDerivedB
}
public class CommonMainClass : IMainClass
{
private readonly IExistable<int> _instance;
public CommonMainClass(IExistable<int> instance)
{
_instance = instance;
}
//this is where you don't depend on IExistable<string>
}
这样,您可以编写更多清晰的代码:
IMainClass a = new CommonMainClass(new DerivedA());
IMainClass b = new ConcreteMainClass(new DerivedB());
ps :最好将依赖项传递到班级生命周期的上层,而不是在内部激活它,因此您可以使用工厂来为您甚至依赖注入创建它们。
ps2 :在抽象类之前使用接口。接口/构造函数/方法描述了您的整体依赖性。另一方面,抽象类只是一种重复使用实现的方式 - 它们并不是要定义接口或与课程的工作方式,您可以将整个身体私有/受保护而无需共享任何内容。