为什么我可以引用ASP.NET 5项目中不包含对该程序集的引用的程序集?

时间:2016-06-16 12:27:29

标签: c# nuget .net-assembly projects-and-solutions asp.net5

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

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

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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

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

没有潜水太深或对#34;最佳实践和#34;做出任何判断这个例子围绕着一个博客的ASP.NET MVC项目。它有一个用于数据访问和业务类的类库。该库安装了NHibernate NuGet包。

  • Foo是" Blog.Mvc" project,ASP.NET MVC应用程序

  • Bar是" Blog.Core" project,包含存储库类和接口的类库,以及" Domain Models"或商务舱。

  • Baz是NHibernate

所以问题就变成了:

  

" Blog.Mvc"应用程序直接使用NHiberate中的类?

没有。 " Blog.Core"项目应该使用存储库接口提供一个抽象层:

Blog.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使用的对象。