我有以下类结构:
interface IA
{
List<IB> Children { get; }
}
interface IB
{
IA Parent { get; }
List<IC> Children { get; }
}
interface IC
{
IB Parent { get; }
List<ID> Children { get; }
}
interface ID
{
IC Parent { get; }
}
实现这些接口的类紧密耦合 - 我们有一组类 XA:A,XB:B,XC:C,XD:D 。 我想要实现的是在编译时知道父和子的确切类型。
泛型是显而易见的方式,但实现对我来说很糟糕:
interface IA<TA, TB, TC, TD>
where TA : IA
where TB : IB
where TC : IC
where TD : ID
{
List<TB> Children { get; }
}
interface IB<TA, TB, TC, TD>
where TA : IA
where TB : IB
where TC : IC
where TD : ID
{
TA Parent { get; }
List<TC> Children { get; }
}
interface IC<TA, TB, TC, TD>
where TA : IA
where TB : IB
where TC : IC
where TD : ID
{
TB Parent { get; }
List<TD> Children { get; }
}
interface ID<TA, TB, TC, TD>
where TA : IA
where TB : IB
where TC : IC
where TD : ID
{
TC Parent { get; }
}
目前它是通过在运行时进行强制实现的,我认为这是不正确的。它是这样的:
class XA : IA
{
//...
}
class XB : IB
{
//...
public XA StronglyTypedParent { get { return (XA) this.Parent; } }
}
应该怎么做?有没有更好的方法来实现这一目标?也许存在解决这种问题的结构模式?任何建议都是最受欢迎的。谢谢。
修改
看来我对这个问题的描述不够明确。让我们考虑一个现实世界的例子:
IA,IB,IC,ID接口对应于在不同时间段执行的一些计算 - 让它们重命名为 IYearCalculation,IMonthCalculation,IWeekCalculation,IDayCalculation 。
我们执行不同的计算,但它们都具有相同的结构 - 例如:
class YearCalculationA : IYearCalculation
class MonthCalculationA : IMonthCalculation
class WeekCalculationA : IWeekCalculation
class DayCalculationA : IDayCalculation
然后,通过
在编译时知道父级和子级的确切类型。
我的意思是,例如,在 DayCalculationA 类中,知道相应年份计算的确切类型( YearCalculationA - 不仅仅是 IYearCalculation )。
我还需要在同一级别上解析之前的计算(例如: DayCalculationA 之前的日计算),这是相同的类型 - 但是我没需要泛型执行运行时转换。
答案 0 :(得分:0)
你可以通过反思来做到这一点:
var sampleClassName = XB.StronglyTypedParent.GetType().FullName;
var newClassInstance = Activator.CreateInstance(Type.GetType(sampleClassName));
但是当你达到这个目的时,你需要问问自己:
“这真的是正确的做法吗?”
这样的聪明技巧使代码不易维护,对新开发人员来说更难理解
答案 1 :(得分:0)
C#不支持返回类型方差,因此这是一个非常常见的问题。我需要时解决它的方法是显式实现接口:
class XA : IA
{
//...
}
class XB : IB
{
private readonly XA parent;
public XA Parent { get { return parent; } }
IA IB.Parent { get { return Parent; } } //XA is implicitly convertible to IA so no ugly castings needed
}
现在任何类似xB.Parent
的表达式都会被输入XA
而iB.Parent
这样的表达式会被输入IA
。你可以获得两全其美的效果。
答案 2 :(得分:0)
泛型通常在某些算法使用抽象而不需要知道实体的每个细节时使用,如果具体描述每个级别你不需要使用泛型,只需编写四个类。
需要了解您的任务更详细的建议,但是如果您的任务即将遍历您的树或抽象操作,您的结构可能是这样的:
interface INode<TParentType, TChildType>: IRoot<TChildType>, ILeaf<TParentType>
{
}
interface IRoot<TChildType>
{
List<TChildType> Children { get; }
}
interface ILeaf<TParentType>
{
TParentType Parent { get; }
}
class FirstLevel : IRoot<SecondLevel>
{
public List<SecondLevel> Children { get; set; }
}
class SecondLevel : INode<FirstLevel, ThirdLevel>
{
public List<ThirdLevel> Children { get; set; }
public FirstLevel Parent { get; set; }
}
class ThirdLevel : INode<SecondLevel, FourthLevel>
{
public List<FourthLevel> Children { get; set; }
public SecondLevel Parent { get; set; }
}
class FourthLevel : ILeaf<ThirdLevel>
{
public ThirdLevel Parent { get; set; }
}
请描述您将对此结构执行哪些操作,如何加载,修改和处理?