继承/架构

时间:2009-10-12 21:22:37

标签: .net architecture inheritance

寻找关于如何构建/构建应用程序的一些指导,我遇到了一些困难。请随意不要限制技术细节的答案,因为我不确定我是否以最有效的方式做事。我在VB.NET中给出了示例,但请随意使用c#,因为这是我们的官方目标语言。我只知道vb更好。此外,我们正在使用Visual Studio 2008。

所以,情景: 我们正在编写一个基于Web的应用程序(希望)可以为多个客户定制。 为了简洁和不放弃农场,让我们说这是一个人事应用程序。

所以,我将有一个Person基类。这将只有非常一般的方法。 它有一个公共财产 类Class1中的名称。

为了论证,接下来我将创建一个新项目/程序集 Person.Employee

现在,由于我可能想将此应用程序出售给模特经纪公司或建筑公司,也许我想添加一些非常奇怪的属性。 CheekStructure或CanOperateHeavyMachinery

所以,我将在工作室中创建新项目 Person.Employee.TinasModeling &安培; Person.Employee.TomsConstructionCompany 它将仅包含特定公司的代码。

您可以假设这些程序集中的每一个都只包含适合层次结构中程序集级别的业务逻辑。

请记住,这是针对许多不同公司的CUSTOM应用程序,但都涉及人事。所以这就是我想出这个模型的原因。如果我们发现较低级别的错误,我只是希望能够修复它并发送一个dll或2.这个结构非常重视我们可能有20个或更多自定义应用程序。分销和维护是PARAMOUNT关注的问题。开发人员不多。比我更多,但不到3 -grin - 。

现在,问题。

为简单起见,我有Class1 in Person。

在我的网络应用程序中,我引用了Person.Employee.TinasModeling 此Web应用程序项目仅适用于Tinas Modeling。

如果我有 Imports Person.Employee.TinasModeling
...

 把它当作新的Class1 D  this.Name =“一些价值”

除非我也引用了Person,否则不会编译。

问题1.我是否真的需要对基类Person(也可能是Person.Employee)的引用,或者是否有某种方法可以不使用它?我不希望任何人意外地在继承链的较低级别创建类。我不确定我是否希望他们在较低级别创建它们,但也许我的担心没有实际意义?

问题2.这是构建此问题的最佳方式吗?请记住,维护和分销是这里的主要问题。想象一个低级错误,不得不打开20个解决方案,构建每个解决方案,测试(即使自动化),构建和分发。 我真的希望有能力发送1个Dll(或者可能是已更新的那个,也是相关的那个?)并且如果那个较低级别的dll通过它的测试那么就完成了

如果我必须对继承树的所有较低级别进行引用,也许我应该将所有这些都放在不同命名空间下的一个程序集中?

Cripes,希望这很清楚。我一整天都在搜索谷歌的遗传样本试图找到有用的东西。希望这里有人可以清除我大脑中的雾气。

提前致谢, 鲍勃

2 个答案:

答案 0 :(得分:1)

听起来像是使用依赖注入的一个很好的候选者 - 为了让您开始在Spring.NET网站上查看this example。对于简短回复表示歉意,但是今晚我可以详细说明我有更多时间坐下来编写一个与您的帖子更相关的快速示例。

修改 好的,首先让我们介绍两个子对象,TinasModeling.Model和BobTheBuilder.Builder

public class Model : IPerson
{
    private bool canAct;
    public bool CanAct
    {
        get { return canAct; }
        set { canAct = value; }
    }

    private double weight;
    public double Weight
    {
        get { return weight; }
        set { weight = value; }
    }

    public Model()
    {
    }

    public bool PayPerson(double Amount)
    {
        if (canAct)
            RequestFilmBoxOfficeRevenue();
        Pay();
    }

    public bool NewJobRequest()
    {
        SendPhotoPortfolioToClient();
        SendJobLocationToModel();
        if (canAct)
            NotifyFilmCrew();
        if (weight < 40.00)
            ContactNutritionist();
    }
}

public class Builder : IPerson
{
    private bool canOperateDigger;
    public bool CanOperateDigger
    {
        get { return canOperateDigger; }
        set { canOperateDigger = value; }
    }

    private double certifiedBuilder;
    public double CertifiedBuilder
    {
        get { return certifiedBuilder; }
        set { certifiedBuilder = value; }
    }

    public Builder()
    {
    }

    public bool PayPerson(double Amount)
    {
        ReuqestTimeSheet();
        Pay();
    }

    public bool NewJobRequest()
    {
        SendBluePrintsToBuilder();
        if (!certifiedBuilder)
            RequestLegalAdvice();
        if (canOperateDigger)
            RequestDrivingPermit();
    }

这两个类都是在不同的项目中实现的 - 它们不一定是,但是出于我稍后会解释的原因。正如你所看到的,他们都做了不同的事情,但有一个共同点,那就是他们实现了IPerson界面。

public interface IPerson
{
    bool PayPerson(double Amount);
    bool NewJobRequest();
}

此接口再次在一个单独的程序集中实现,而不是上述两个对象,因此我们的子对象引用此程序集,我们称之为BOL(业务对象层)。在BOL中,我们实现了另一个名为PersonController的类

public class PersonController
{
    private IPerson thePerson;
    public IPerson ThePerson
    {
        get { return this.thePerson; }
        set { this.thePerson = value; }
    }

    public PersonController()
    {
    }

    public bool PayPerson(double Amount)
    {
        return this.thePerson.PayPerson(Amount);
    }

    public bool NewJob()
    {
        return this.thePerson.NewJobRequest();
    }
}

关于PersonController最值得注意的是ThePerson属性。这将是我们的依赖注入点。值得指出的是,在这个阶段,BOL层与任何子对象完全分离。这是一项重要功能,可以为部署和维护时间提供很大的灵活性。

现在我们使用和配置到目前为止我们已经构建的内容。我们的应用程序仅引用BOL层(也将我们的主应用程序与任何子对象分离)。在我们的主应用程序中,我们使用Spring.NET Spring.Core程序集,在app.config文件中我们添加以下内容(为了便于阅读,我省略了configSections标记)

  <spring>
<context>
  <resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
  <description>An  example that demonstrates simple IoC features.</description>
  <object name="Person"  type="BOL.BOL.PersonController, BOL.BOL">
    <property name="ThePerson" ref="Person"/>
  </object>
  <object name="Person" type="BobTheBuilder.BobTheBuilder.Builder, BobTheBuilder.BobTheBuilder">
  </object>
</objects>

好的希望每个人都和我在一起 - 第一个对象元素指的是需要依赖注入的类,在我们的例子中是PersonController。 child属性元素引用PersonController中的依赖注入点,或者在我们的例子中引用ThePerson属性。此元素的ref属性引用我们的第二个对象元素。

第二个对象元素我们设置了我们希望在运行时注入的子对象(即TinasModeling.Model或BobTheBuilder.Builder)。

最后将所有内容放在一起的代码

    static void Main(string[] args)
    {
        IApplicationContext ctx = ContextRegistry.GetContext();
        PersonController person = (PersonController)ctx.GetObject("Person");

        // Ready to use person with implementation specified in config
        person.NewJob();
        person.PayPerson();
    }

所以这将根据我们在app.config中配置“Person”的方式来实例化PersonController。

所以问题一的答案是否定的(至少如上所述) - 你完全分开你的基础实现。

问题二的答案(这是构建此的最佳方式)可能有点主观 - 但在我看来,配送和维护是您主要关心的问题,上述设计满足您的需求因为实际上对重物提升的组件完全解耦了。

希望我已经很好地解释了自己。

答案 1 :(得分:0)

作为一般原则,树根处的类都应该是抽象的,因为它们都是不完整的。

当只有特定于各个客户应用程序的类型具体化时,您无意中创建其他类的问题就会消失。