1

我有一个名为 Foo 的 DNX 4.5.1 ASP.NET 5 项目和一个名为 Bar 的类库项目。Foo 引用了 Bar,而 Bar 引用了一个名为 Baz 的 nuget 包。

在 Foo 中,我可以使用 Baz 中定义的类型,尽管 Foo 没有引用该 nuget 包。似乎 Foo 可以访问 Bar 引用的任何类型。这是为什么?这不是完全打破了抽象的概念吗?

4

1 回答 1

1

不,只要您在 Foo 中安装 Baz NuGet 包,它就不会破坏抽象,因为您声明了一个依赖项。Baz 库具有公共类这一简单事实意味着任何引用它的 exe 或 dll 文件都可以使用这些类。

由于 Foo 需要 Bar,而 Bar 需要 Baz,所以编译 Foo 时 Baz.dll 文件应该出现在bin/输出文件夹中,因为 Foo 需要 Bar 中的类。using这意味着Foo 中文件顶部的简单指令会导致 CLR 导入 Baz.dll 文件。

现在,如果 Foo 需要直接使用 Baz 中定义的类,我建议将 Baz 项目安装为 Foo 的依赖项。两个库需要同一个第三方库是可以的。您只需要确保 Foo 和 Bar 都需要相同的版本。

如果 Foo 和 Bar 需要不同的版本,那么我建议在 Bar 中创建代理类或接口来封装您需要从 Baz 获得的行为,这样 Foo 项目就不需要直接了解 Baz。

让我们做一个具体的例子。

示例:使用 NHibernate 的博客 Web 应用程序

在没有深入研究或对“最佳实践”做出任何判断的情况下,此示例围绕博客的 ASP.NET MVC 项目展开。它有一个用于数据访问和业务类的类库。该库安装 NHibernate NuGet 包。

  • Foo 是“Blog.Mvc”项目,一个 ASP.NET MVC 应用程序

  • Bar 是“Blog.Core”项目,一个包含存储库类和接口的类库,以及“域模型”或业务类。

  • Baz 是 NHibernate

于是问题就变成了:

“Blog.Mvc”应用程序是否应该直接使用 NIBerate 中的类?

不,“Blog.Core”项目应该使用存储库接口提供一个抽象层:

博客.Core

一、“域模型”或业务类:

public class Blog
{
    public virtual int Id { get; protected set; }
    public virtual string Name { get; set; }
}

博客存储库的公共接口:

public interface IBlogRepository
{
    Blog Find(int id);
}

现在接口的实现,引用与NHibernate直接相关的类和接口:

public class BlogRepository : IBlogRepository
{
    private NHibernate.ISession session;

    private NHibernate.ISession Session
    {
        get
        {
            if (session == null)
                session = NHibernateSessionHelper.GetSession();

            return session;
        }
    }

    public Blog Find(int id)
    {
        return Session.Get<Blog>(id);
    }
}

MVC 项目控制器通过其接口使用存储库:

public class BlogsController : Controller
{
    public BlogsController(IBlogRepository repository)
    {
        this.repository = repository;
    }

    private IBlogRepository repository;

    public ActionResult Edit(int id)
    {
        Blog blog = repository.Find(id);

        if (blog == null)
            return HttpNotFound();

        BlogForm viewModel = new BlogForm(blog);

        return View(viewModel);
    }
}

虽然这可能不是您的确切情况,但此示例中概述的关注点分离使您的问题没有实际意义。

如果 Foo 需要 Baz 中的类,请将其声明为依赖项。如果没有,请不要在 Foo 项目中使用 Baz 中声明的类。如果 Foo 需要来自 Bar 的功能,该功能将某些行为委托给 Baz,只要 Foo 没有为 Baz 中定义的类传递任何对象,这不会破坏抽象。Bar 需要创建自己的类作为数据传输对象、代理类或实现 Bar 中定义的接口以在 Foo 中使用的某种对象。

于 2016-06-16T12:54:57.997 回答