2

在编写新类和代码时,我试图遵循 SOLID 原则。

我的问题是关于扩展 Page 类的 ASP.NET 类,即 ASPX 文件。如果我有一个页面类,它有一个 page_load 事件,它创建多个对象的实例,例如 Person 类、Sport 类等,那么我相信这个页面类与这些类紧密耦合。是这种情况还是我遗漏了一些明显的东西?是不是所有的类都应该公开接口,而客户端(aspx 页面)应该使用接口而不是直接实例化类。

如果涉及多态性,我发现接口很有用,例如使用学生接口在运行时创建研究生或本科生的实例。所有类都应该有接口吗?

4

3 回答 3

1

如果您在Page类(表示层)中创建实体,则显然违反了单一职责原则,因为页面类将有多种更改原因。

相反,将此逻辑移至业务层并创建处理此逻辑的服务。

您的页面将需要与服务接口对话,而不是与实现 (DIP) 对话,并且此服务接口需要窄化 (ISP);可能只有一种方法。

如果您将服务的所有参数打包到一个对象中,从而分离数据和行为,并为您的服务使用通用接口(即ICommandHandler<TCommand>),您甚至可以遵守 OCP,因为您现在可以添加行为(例如验证、事务、死锁检测、异步处理、排队)到服务,而对应用程序没有任何更改。

最后一点,不要为实体创建接口。这是相当无用的,并且模糊了您的代码。

于 2012-07-27T18:38:26.017 回答
0

我不会在后面的代码中实例化对象。我所做的是调用一个实例化获取对象的服务——它用数据库中的数据实例化它们。我还在母版页中公开了该服务,并像这样引用它:

IUser _user = (Page.Master as MasterBase).RegistrationService.GetPersonFromEmailAddress(txtUser.text);

当然,您应该检查以确保 (Page.Master as MasterBase) 不为空......


按要求编辑

我创建了一个基础母版页,所有其他站点母版页都必须继承自该母版页。在这个基本母版页的构造函数中,我实例化了所有必要的服务。当然,如果服务没有在整个站点中使用,它们可以在不同的、更合适的部分通用母版页上实例化。

public readonly IRegistration RegistrationService;
public readonly IEventService EventService;
public readonly IEmailSendingService EmailService;
private readonly IMenuService _menuService;

public MasterBase()
{
    RegistrationService = new BusinessLogic.Registration(DatabaseConnectionString);
    EventService = new EventService(DatabaseConnectionString);

    var fromAddress = ConfigurationManager.AppSettings["Webmaster"];
    var defaultToEmailAddress = ConfigurationManager.AppSettings["toEmail"];
    EmailService = new EmailSendingService(BaseUrl, fromAddress, defaultEmailAddress);
    _menuService = new MenuService(DatabaseConnectionString);
}

如上所述,网站上使用的任何母版页都将从基础继承:

public partial class MasterContent : MasterBase

任何引用母版页的 UI 页面(在我的例子中几乎全部)

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="activities.aspx.cs" Inherits="activities" MasterPageFile="~/MasterContent.Master" %>

现在可以访问后面代码中的不同服务:

IUser _user = (Page.Master as MasterBase).RegistrationService.GetPersonFromEmailAddress(txtUser.text);

正如下面评论中提到的,不同的 UI 页面确实与基本母版页紧密耦合,但我不知道在一般的 ASP.NET Web 表单应用程序中有什么更好的方法来做到这一点。它减少了在每个 UI 页面上实例化服务的需要,并且从特定于项目的角度来看,使所有母版页都继承自该基本页面是可以接受的。

于 2012-07-27T15:17:23.467 回答
0

您可以这样做的一种方法是在 Global.asax 中配置您的依赖项

public static void RegisterRoutes(RouteCollection routes)
{
    routes.MapPageRoute("",
        "Create/{Service}",
        "~/categoriespage.aspx",{"Service", new WhatEverSErvice()} );
}

您需要在哪里适应 URL 模式和文件路径以适应您的网站。这将通过 Service 路由值为您提供服务对象的句柄

然后,您可以声明一个基页类

public abstract class BasePage<TService> : Page where TService : IService {

   protected TService Service{
       get {
           return Page.RouteData.Values["Service"] as TService;
       }
   }
}

IService是您必须定义的接口,它是您的服务的基础(如果这样的接口有意义,否则只需省略 where 子句)

然后让你的所有页面都从这个类派生,当你需要你的特定服务时,你只需编写类似的东西

var myFoo = Service.CreateFoo();

当用户在 / 之后提供一个字符串时,这种方法在错误情况下确实有点奇怪。您可以通过扩展属性来处理这个问题,因为它基本上是一个未找到的文件(提供的 URL 无效)您可以返回 404 FNF 响应

于 2012-07-30T12:59:35.777 回答