我有一个名为 Foo 的 DNX 4.5.1 ASP.NET 5 项目和一个名为 Bar 的类库项目。Foo 引用了 Bar,而 Bar 引用了一个名为 Baz 的 nuget 包。
在 Foo 中,我可以使用 Baz 中定义的类型,尽管 Foo 没有引用该 nuget 包。似乎 Foo 可以访问 Bar 引用的任何类型。这是为什么?这不是完全打破了抽象的概念吗?
我有一个名为 Foo 的 DNX 4.5.1 ASP.NET 5 项目和一个名为 Bar 的类库项目。Foo 引用了 Bar,而 Bar 引用了一个名为 Baz 的 nuget 包。
在 Foo 中,我可以使用 Baz 中定义的类型,尽管 Foo 没有引用该 nuget 包。似乎 Foo 可以访问 Bar 引用的任何类型。这是为什么?这不是完全打破了抽象的概念吗?
不,只要您在 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。
让我们做一个具体的例子。
在没有深入研究或对“最佳实践”做出任何判断的情况下,此示例围绕博客的 ASP.NET MVC 项目展开。它有一个用于数据访问和业务类的类库。该库安装 NHibernate NuGet 包。
Foo 是“Blog.Mvc”项目,一个 ASP.NET MVC 应用程序
Bar 是“Blog.Core”项目,一个包含存储库类和接口的类库,以及“域模型”或业务类。
Baz 是 NHibernate
于是问题就变成了:
“Blog.Mvc”应用程序是否应该直接使用 NIBerate 中的类?
不,“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 中使用的某种对象。