为什么我可以在 ASP.NET 5 项目中引用一个不包含对该程序集的引用的程序集?
Why can I reference an assembly in an ASP.NET 5 project that doesn't include a reference to that assembly?
我有一个名为 Foo 的 DNX 4.5.1 ASP.NET 5 项目和一个名为 Bar 的 class 库项目。 Foo 引用了 Bar,而 Bar 引用了一个名为 Baz 的 nuget 包。
在 Foo 中,我可以使用 Baz 中定义的类型,尽管 Foo 没有引用 nuget 包。看起来 Foo 可以访问 Bar 引用的任何类型。这是为什么?这不是完全打破了抽象的概念吗?
不,只要您也在 Foo 中安装 Baz NuGet 包,它就不会破坏抽象,因为您声明了依赖项。 Baz 库具有 public classes 的简单事实意味着任何引用它的 exe 或 dll 文件都可以使用那些 classes.
由于 Foo 需要 Bar,而 Bar 需要 Baz,因此在编译 Foo 时 Baz.dll 文件应该出现在 bin/
输出文件夹中,因为 Foo 在 Bar 中需要 classes。这意味着 Foo 中文件顶部的简单 using
指令会导致 CLR 导入 Baz.dll 文件。
现在如果 Foo 需要直接使用 Baz 中定义的 classes,我建议安装 Baz 项目作为 Foo 的依赖项。两个库需要同一个第三方库是可以的。您只需要确保 Foo 和 Bar 都需要相同的版本。
如果 Foo 和 Bar 需要不同的版本,那么我建议在 Bar 中创建代理 classes 或接口来封装你需要的 Baz 的行为,这样 Foo 项目就不需要直接知道关于巴兹
举个具体的例子吧
示例:使用 NHibernate 的博客 Web 应用程序
无需深入研究或对 "best practices" 做出任何判断,此示例围绕博客的 ASP.NET MVC 项目展开。它有一个用于数据访问和业务 class 的 class 库。该库安装 NHibernate NuGet 包。
Foo 是 "Blog.Mvc" 项目,一个 ASP.NET MVC 应用程序
Bar 是 "Blog.Core" 项目,一个包含存储库 classes 和接口的 class 库,以及 "Domain Models" 或业务 classes.
Baz 是 NHibernate
所以问题变成:
Should the "Blog.Mvc" application directly uses classes from NHiberate?
没有。 "Blog.Core" 项目应该使用存储库接口提供一个抽象层:
Blog.Core
首先,"Domain Model"或业务class:
public class Blog
{
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
}
博客存储库的 public 界面:
public interface IBlogRepository
{
Blog Find(int id);
}
现在实现接口,引用classes和与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 中需要 classes,请将其声明为依赖项。如果不是,请不要在 Foo 项目中使用 Baz 中声明的 classes。如果 Foo 需要来自 Bar 的功能将某些行为委托给 Baz,那么只要 Foo 没有传递 Baz 中定义的 classes 的任何对象,这就不会破坏抽象。 Bar 需要创建自己的 classes 作为数据传输对象、代理 classes 或某种实现 Bar 中定义的接口以供 Foo 使用的对象。
我有一个名为 Foo 的 DNX 4.5.1 ASP.NET 5 项目和一个名为 Bar 的 class 库项目。 Foo 引用了 Bar,而 Bar 引用了一个名为 Baz 的 nuget 包。
在 Foo 中,我可以使用 Baz 中定义的类型,尽管 Foo 没有引用 nuget 包。看起来 Foo 可以访问 Bar 引用的任何类型。这是为什么?这不是完全打破了抽象的概念吗?
不,只要您也在 Foo 中安装 Baz NuGet 包,它就不会破坏抽象,因为您声明了依赖项。 Baz 库具有 public classes 的简单事实意味着任何引用它的 exe 或 dll 文件都可以使用那些 classes.
由于 Foo 需要 Bar,而 Bar 需要 Baz,因此在编译 Foo 时 Baz.dll 文件应该出现在 bin/
输出文件夹中,因为 Foo 在 Bar 中需要 classes。这意味着 Foo 中文件顶部的简单 using
指令会导致 CLR 导入 Baz.dll 文件。
现在如果 Foo 需要直接使用 Baz 中定义的 classes,我建议安装 Baz 项目作为 Foo 的依赖项。两个库需要同一个第三方库是可以的。您只需要确保 Foo 和 Bar 都需要相同的版本。
如果 Foo 和 Bar 需要不同的版本,那么我建议在 Bar 中创建代理 classes 或接口来封装你需要的 Baz 的行为,这样 Foo 项目就不需要直接知道关于巴兹
举个具体的例子吧
示例:使用 NHibernate 的博客 Web 应用程序
无需深入研究或对 "best practices" 做出任何判断,此示例围绕博客的 ASP.NET MVC 项目展开。它有一个用于数据访问和业务 class 的 class 库。该库安装 NHibernate NuGet 包。
Foo 是 "Blog.Mvc" 项目,一个 ASP.NET MVC 应用程序
Bar 是 "Blog.Core" 项目,一个包含存储库 classes 和接口的 class 库,以及 "Domain Models" 或业务 classes.
Baz 是 NHibernate
所以问题变成:
Should the "Blog.Mvc" application directly uses classes from NHiberate?
没有。 "Blog.Core" 项目应该使用存储库接口提供一个抽象层:
Blog.Core
首先,"Domain Model"或业务class:
public class Blog
{
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
}
博客存储库的 public 界面:
public interface IBlogRepository
{
Blog Find(int id);
}
现在实现接口,引用classes和与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 中需要 classes,请将其声明为依赖项。如果不是,请不要在 Foo 项目中使用 Baz 中声明的 classes。如果 Foo 需要来自 Bar 的功能将某些行为委托给 Baz,那么只要 Foo 没有传递 Baz 中定义的 classes 的任何对象,这就不会破坏抽象。 Bar 需要创建自己的 classes 作为数据传输对象、代理 classes 或某种实现 Bar 中定义的接口以供 Foo 使用的对象。