如何在不同层中的多态类之间保持一对一的关系?

时间:2013-11-15 11:57:58

标签: c# design-patterns mvvm polymorphism factory

我有一个域逻辑层,其中存在一个抽象超类,我们称之为 DomainAbstractClass

许多具体的类继承自这个类,让我们称之为 ConcreteDomainClass1 ConcreteDomainClass2 等等。

现在,在一个不同的程序集中,这是我的表示逻辑层,我有一个类似的层次结构,其中一个抽象的超类,我们称之为 PresentationAbstractClass ,由许多具体的类实现 ConcretePresentationClass1 ConcretePresentationClass2 等。

ConcreteDomainClass1 ConcretePresentationClass1 ConcreteDomainClass2 ConcretePresentationClass2 之间存在自然的一对一关系, etc ...因为表示类封装了每个特定域实体的特定表示逻辑。

由于我希望保持我的域逻辑层尽可能不依赖,我的表示逻辑层有一个对域逻辑层的引用,但不是相反。

现在,表示逻辑层调用域逻辑层中返回 AbstractDomainClass 的方法,我需要根据创建适当的 ConcretePresentationClassN ConcreteDomainClassN 抽象域类确实是。

是否有一种创造性的模式可以让我在不必诉诸这种丑陋的事情的情况下实现这一目标?

if(abstractClass is ConcreteDomainClass1)
    new ConcretePresentationClass1();

else if (abstractClass is ConcreteDomainClass2)
    new ConcretePresentationClass2();

// ... and so on

3 个答案:

答案 0 :(得分:0)

我建议使用工厂模式,将整个事物包装在一个简单的工厂方法中,并使用字典在类之间进行映射:

private Dictionary<Type, Func<DomainAbstractClass, PresentationAbstractClass>> factory = 
    new Dictionary<Type, Func<DomainAbstractClass, PresentationAbstractClass>>
    {
        { typeof(ConcreteDomainClass1), (x) => new ConcretePresentationClass1(x) },
        { typeof(ConcreteDomainClass2), (x) => new ConcretePresentationClass2(x) },
        ....
    };

public PresentationAbstractClass ObtainPresentationClassFromDomainClass(DomainAbstractClass domainClass)
{
    return factory[domainClass.GetType()](domainClass);
}

答案 1 :(得分:0)

情况如下:

 ---Presentation layer---   ---Domain layer---   ---Repository layer---
1.  --- control flow --->    --- control flow--->   --- control flow---
2.  --- creation of PO---   <-- creation of DO --    <----- data -----|

其中创建DO 是创建特定域对象,而创建PO 是创建特定的表示对象,这取决于域对象类型,这取决于数据。

这种依赖关系不可避免地使所需表示对象的类型依赖于数据。这在某种程度上是正常的情况,但这里的创建控制流似乎是某种对这种模式的恶劣条件。通常,“创建链”是这样的: View 实例化(或引用)引用特定 Model ViewModel

因此,唯一的解决方案(不考虑重新设计)是使用某种注册表/工厂,它根据域对象的类型创建适当的表示对象。遗憾的是,这相当于切换对象的类型。

答案 2 :(得分:0)

你的问题有点不清楚。我得到的是你想要根据另一个表示类的输入创建一个表示类,该表由类域处理。

如果你想要神奇地解析/生成它,那里有一些IOC容器可以帮助你通过逻辑和配置(AutoFac,Simple Injector,Castle Windsor等)来解决具体的类。但是我没有任何经验,所以我不能分享太多(但我知道那些容器具有配置的能力)。

对于您的起点,该技术名为Convention over Configuration,由Asp.Net MVC控制器使用 - 查看解析器。

但是,这是使用反射的手动逻辑:

public AbstractFactory{
    public AbstractFactory (IConfiguration config){
        this.presentationClassNameSpace = config.PresentationClassNameSpace;
    }
    private readonly string presentationClassNameSpace;
    public AbstractPresentationClass Resolve(Type t){
        string className = t.Name;
        className = className.Replace("Domain", "Presentation");
        AbstractPresentationClass resultClass = 
            (AbstractPresentationClass) System.Activator.CreateInstance(
                Type.GetType(presentationClassNameSpace + "." + className);
        return resultClass;
    }
}

注意:

如果要注入AbstractDomainClass,可以使用泛型类型而不是类型t,并且基于注入的对象,您可以按GetType();获得类型。优点是您可以使用特定方法创建另一个抽象工厂,具体来自给定具体的域类。

或者您可以注入AbstractDomainClass,然后按GetType();获取类型。

如果需要,您可以在方法级别使用泛型来根据需要解析类型,但我不推荐它。