如何正确地将结构映射依赖解析器与 ASP.NET MVC Web 项目解耦?

发布于 2024-10-16 05:57:30 字数 1004 浏览 1 评论 0原文

在使用 ASP.NET MVC 开发 Web 项目时,我遇到了耦合问题。 当我构建自定义控制器工厂(或依赖项解析器,如果使用 MVC 3)时,我需要这个工厂以某种方式知道从哪里获取依赖项。这是我的代码:

//from Global.asax.cs

DependencyResolver.SetResolver(new StructureMapControllerFactory());
class StructureMapControllerFactory: IDependencyResolver {
    Container repositories;

    public StructureMapControllerFactory()
    {
        repositories = new RepositoriesContainer();
    }
    //... rest of the implementation
}
class RepositoriesContainer: Container
{
   public RepositoriesContainer()
   {
      For<IAccountRepository>().Use<SqlAccountRepository>();
      //...
   }
}

StructureMapControllerFactory 类负责将依赖项注入控制器。正如我所说,它需要知道在哪里可以找到这些依赖项(我的意思是具体的类,例如服务和存储库实现)。

我有一个名为 MySite.Data 的单独类库,其中包含所有实现细节。合约(例如 IAccountRepository)位于库 MySite.Contracts 中。现在,如果我直接从 MVC 项目引用此 MySite.Data 库,我的站点及其数据检索的实现之间将存在依赖关系。问题是我怎样才能删除它?这种情况下的最佳做法是什么?

我确信它确实有很多解决方法,只是我还没有找到。

While developing web project using ASP.NET MVC, I came up against a coupling problem.
When I build custom controller factory (or dependency resolver if using MVC 3), I need this factory to know somehow where to get dependencies from. Here's my code:

//from Global.asax.cs

DependencyResolver.SetResolver(new StructureMapControllerFactory());
class StructureMapControllerFactory: IDependencyResolver {
    Container repositories;

    public StructureMapControllerFactory()
    {
        repositories = new RepositoriesContainer();
    }
    //... rest of the implementation
}
class RepositoriesContainer: Container
{
   public RepositoriesContainer()
   {
      For<IAccountRepository>().Use<SqlAccountRepository>();
      //...
   }
}

StructureMapControllerFactory class is responsible for injecting dependencies into a controller. As I said, it needs to know where to find these dependencies (I mean concrete classes, like services and repositories implementations).

I have a separate class library called MySite.Data, where all the implementation details live. Contracts, like IAccountRepository, live in library MySite.Contracts. Now, if I reference this MySite.Data library directly from MVC project, there will be a dependency between my site and implementation of its data retrieval. The question is how can I remove it? What are best practices in this situation?

I'm sure it does have a bunch of workarounds, just I haven't found any yet.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

木落 2024-10-23 05:57:30

嗯,据我所知,你不能完全这样做。您的 MVC 项目确实需要了解它将使用的具体类。

无论如何,您都必须在某处提供这些容器注册,并且您将获得对定义该类型的项目/程序集的依赖关系。很快,您必须从 MVC 项目引用 MySite.Data。就像这样:

  • MySite.Data 对 MVC 项目一无所知
  • MVC 项目知道具体的存储库类型以提供正确的容器注册。

您可以使用 StructureMap Registry 对象让生活变得更简单,但您也需要在某处包含这些注册表。通常这些位于主项目或某些“StructureMap-adapter”项目中,但无论如何您都需要进行参考。

我建议您:

  • 使用 MVC3 并删除您的自定义 IControllerFactory(如果您仅将其用于 Controllers 中的 DI)。
  • 使用 StructureMap Registry 对象来提供所需的每个 IoC 注册。
  • 使用 StructureMap 组件扫描功能来提供组件发现。
  • 使用更常见的东西作为 DependencyResolver,即不是 StructureMapControllerFactory 而是 CommonServiceLocator 改为 StructureMap 适配器
  • 尝试从主应用程序中的 StructureMap 本身进行抽象。

当然,不要害怕在主项目中进行引用 - 它们与耦合无关。它不会降低可维护性。但错误的架构确实如此,所以要担心这一点,而不是简单的参考。

Well, as I see it, you can't do exactly that. Your MVC project really really needs to know about concrete classes it is going to use.

You will anyway have to provide those container registrations somewhere and you'll get the dependency on the project/assembly where that type is defined. Shortly, you have to reference MySite.Data from MVC project. Like that:

  • MySite.Data knows nothing about MVC project
  • MVC project knows the concrete repositories types to provide correct container registrations.

You can make life simpler with StructureMap Registry objects but you need to include those Registries somewhere as well. Typically those are in the main project or some "StructureMap-adapter" project but you'd need to make reference anyway.

I'd advise that you:

  • Use MVC3 and drop your custom IControllerFactory if you only use it for DI into your Controllers.
  • Use StructureMap Registry objects to provide each and every IoC registration ever needed.
  • Use StructureMap Assembly scanning capabilities to provide components discovery.
  • Use something much more common as a DependencyResolver, i.e. not a StructureMapControllerFactory but a CommonServiceLocator with StructureMap adapter instead.
  • Try to abstract from StructureMap itself inside your main app.

And, of course, don't be afraid of making references inside the main project - they have nothing about coupling. It doesn't decrease maintainability. But the wrong architecture does, so be worried about that, not simple reference.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文