我使用的是通用的存储库模式坚持我的数据。在pageLoad的,我创建一个新的存储库(从IRepository)对象,并在PageUnload,我处置。

应该母版/页负责实例化的对象的传递到演示者或应呈现者负责这个?我更关心的是测试演示比页面(查看),因为它更容易嘲笑传递给主持人的接口。

示例页

public partial class _Default : System.Web.UI.Page
{
    private IRepository _repo;
    protected void Page_Load(object sender, EventArgs e)
    {
        if (_repo == null)
            _repo = new Repository();
        ConnectPresenter();
    }

    private void ConnectPresenter()
    {
        _DefaultPresenter presenter = new _DefaultPresenter(_repo);
    }

    private void Page_Unload(object sender, EventArgs e)
    {
        if (_repo != null)
            _repo.Dispose();
    }
}

说一个DI框架如StructureMap或在这种情况下Ninject帮助?难道是负责处置的对象,如这个呢?

有帮助吗?

解决方案

无论是Page类,也不是主持人应该具有直接管理的任何依赖的建设或生命周期来处理 - 这都应该由你的容器来处理。由于构造函数注入不与的WebForms工作,你将需要公开任何需要的依赖关系的类属性。例如,你可以在你的类更改为:

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }

    public _DefaultPresenter Presenter { get; set; }
}

在页不应该需要到仓库的任何参考,因为它会被注入到演示。

此答案的其余部分是特定于StructureMap - 细节可用于其它容器的不同

要启用setter注入,你需要告诉StructureMap来填充其属性。一种方法是到[SetterProperty]属性适用于财产本身。然而,这可能觉得有点侵入对你的类内StructureMap细节。另一种方法是配置StructureMap以便它知道注入哪些物业类型。例如:

protected void Application_Start(object sender, EventArgs e)
{
    ObjectFactory.Initialize(x =>
    {
        x.Scan(scan =>
        {
            scan.TheCallingAssembly();
            scan.WithDefaultConventions();
        });
        x.ForRequestedType<IRepository>().TheDefaultIsConcreteType<Repository>().CacheBy(InstanceScope.Hybrid);
        x.SetAllProperties(set => set.WithAnyTypeFromNamespaceContainingType<IRepository>());
    });
}

在SetAllProperties方法允许你告诉StructureMap如何识别它应该填充特性。在这种情况下,我要告诉StructureMap注入所有演示者(假定它们都在相同的命名空间)。

您仍需要对每个请求进行setter注入。随着StructureMap,您可以使用累积()方法注入依赖到现有实例。你可以做到这一点在每个页面或页面基类的初始化或加载事件,但同样,那种感觉侵入。为了保持容器您的页面类的完全,您可以使用该应用程序的事件的PreRequestHandlerExecute(在Global.asax中或IHttpModule的):

protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
    var application = (HttpApplication)sender;
    var page = application.Context.CurrentHandler as Page;
    if (page == null) return;
    ObjectFactory.BuildUp(page);
}

最后,如果你想明确地处置您的IRepository的,你可以处理,在EndRequest事件:

protected void Application_EndRequest(object sender, EventArgs e)
{
    var disposable = ObjectFactory.GetInstance<IRepository>() as IDisposable;
    if (disposable != null) disposable.Dispose();
}

请注意,此工作正常,因为在初始化我们告诉StructureMap的混合,这意味着缓存IRepository“给我的每一个HTTP请求相同的实例(或线程,如果没有一个网站中运行)”。当检索EndRequest的IRepository,将收到整个请求所用的相同,并且可以处理它。

其他提示

是的,这将是非常值得你调查之一所述预排有使用DI与ASP.NET 的。

是,每个请求行为处置对象在适当的点一般是由容器的与ASP.NET集成管理。

在典型的布置是,对象创建从页面和Application / Modules向内流动。一般来说,你标记属性您[Inject]Page,但它取决于你如何安排你的黑社会。演示者一般可以使用注射Constructo声明,无论它需要什么无论是其测试或ASP.NET cotext的。然后在运行时,依赖将由DI满足。在测试时,你仍然可以使用DI,但在其他情况下,它可能是更自然与SUT一起只是创建了一堆假货,并通过这些给演示。

关于triead安排WRT测试,我发现与xUnit.net由Justin Etheredge 的非常有用的,即使它的在ASP.NET MVC针对性。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top