我使用通用工厂类,其中通用部分是正在使用的派生类。正常用法很明确:BaseClass<DerivedA> C = new BaseClass<DerivedA>().
现在虽然我试图将属性注入到我使用这些类的类中。为此,我尝试将Type作为参数(以便我可以注入正在使用的派生类)。
尽管我有点不知所措,尽管我正在寻找自己的例子并试图自己。我现在想知道:这样的构造是否可以使用?如果是这样,我如何实例化该类并使用Exists和ExistsB?
用法:
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) {...}
}
答案 0 :(得分:4)
您可以使用以下方法创建任何类型的实例:
_ClassInstance = Activator.CreateInstance(typeIWant)
不建议使用,因为当您想要使用其中一种BaseClass方法时,您将永远检查其类型并进行转换。如果您能够更改主类以获取类型参数,它应如下所示:
public class MyMainClass<T> where T: BaseClass<T>, new()
{
T _ClassInstance; // BaseClass<DerivedA> or BaseClass<DerivedB>
public MyMainClass()
{
_ClassInstance = new T();
}
}
这将允许您使用BaseClass上定义的任何方法。如果你想使用ExistsB,那么你仍然需要在运行时检查它的类型并进行转换。我会推荐这样的东西:
if (_ClassInstance is DerivedB derivedB)
derivedB.ExistsB("...");
如果你真的需要编译时检查,我会推荐它,你的课程需要改变。您不能仅使用对基类的引用来访问派生类上定义的方法或属性。
答案 1 :(得分:1)
这是你想要的吗?
import itertools
答案 2 :(得分:0)
我建议您使用getType
来获取类型名称。如果您升级继承(从DerivedB等继承另一个类),如果使用getType
,您可以确保仅为DerivedB类型的实例调用此方法。
MyMainClass b = new MyMainClass(typeof(DerivedB));
if(b.GetType() == typeof(DerivedB))
b.ExistsB(...);
答案 3 :(得分:0)
这是抽象类的主要问题 - 您共享接口和实现。但在您的情况下,您强烈依赖于不同的接口。为了简化问题,只需看看你真正想要的东西:
public interface IExistable<in TValue>
{
bool Exists(TValue value);
}
public interface IDerivedA : IExistable<int>
{
}
public interface IDerivedB : IExistable<int>, IExistable<string>
{
}
正如您所看到的,您使用两个接口过度复杂IDerivedB,即您的MainClass在某些情况下依赖于IDerivedB。扩展接口也不错,你只是错误地使用它。所以你必须做的是定义MainClass的接口:
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 :在抽象类之前使用接口。接口/构造函数/方法描述了您的整体依赖关系。另一方面,抽象类只是重用实现的一种方式 - 它们不是用来定义接口或者你如何使用类,你可以使整个主体私有/受保护而不会分享任何东西。