C#耦合类 - 强类型结构设计

时间:2016-06-17 12:44:43

标签: c# .net design-patterns

我有以下类结构:

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 之前的计算),这是相同的类型 - 但是我没需要泛型执行运行时转换。

3 个答案:

答案 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的表达式都会被输入XAiB.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; }
    }

请描述您将对此结构执行哪些操作,如何加载,修改和处理?