【问题标题】:Entity Framework CTP5 and Ninject as my IOCEntity Framework CTP5 和 Ninject 作为我的 IOC
【发布时间】:2010-12-30 11:39:00
【问题描述】:

是否可以在实体框架 CTP5 中通过 IOC 容器构造检索到的持久实体?

我正在使用 Ninject,它与 MVC 很好地结合在一起,但是当为某些业务规则构造它们时,我需要将一些服务注入到我的域对象中。

我宁愿使用构造函数注入而不是方法或属性注入来做到这一点。

【问题讨论】:

    标签: entity-framework ioc-container ninject entity-framework-ctp5


    【解决方案1】:

    我不确定您究竟想在这里完成什么,但 EF 几乎没有可扩展性点。您可以做的最好的事情是挂钩到由 ObjectContext 触发的 ObjectMaterialized 事件。在 CTP5 中,您需要在 DbContext 的构造函数中像这样转换 DbContext:

    ((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += 
        this.ObjectContext_OnObjectMaterialized;
    

    然后实现你的函数ObjectContext_OnObjectMaterialized(object sender, ObjectMaterializedEventArgs e)。您将能够访问您的对象,不幸的是,该对象已经物化了。根据您的需要,您也许可以在这里破解一些有趣的行为。

    顺便说一句,这句话对我来说毫无意义:

    当为某些业务规则构建域对象时,我需要将一些存储库注入到我的域对象中。

    这不违反 Persistence Ignorant Domain Objects 吗?

    【讨论】:

    • 存储库一词应该是服务(我已经更新了我的原始版本)。例如,一个域对象可能有一些电子邮件发送功能,所以我想在构建时注入一个电子邮件服务。
    • @WDuffy - 有道理。不幸的是,MS 论坛中的此响应 (social.msdn.microsoft.com/Forums/en/adonetefx/thread/…) 证实,由于 EF 需要零参数构造函数来实现您的 POCO,因此您不能使用经典的构造函数注入。唯一的解决方法是 1) 使此构造函数成为内部构造函数,然后 2) 使此构造函数调用具有由 IoC 容器解析的参数的构造函数。不幸的是,这会因 IoC 问题而污染您的 POCO。
    • ICustomerRepository 接口对持久性无知。如果您阅读 DDD 蓝皮书,您会注意到 Eric Evans 甚至在一些详细的序列图中这样做。这就是存储库的意义所在,如果它们真的是存储库而不仅仅是花哨的数据访问对象的话。我个人在聚合根中使用存储库接口,效果很好。
    【解决方案2】:

    我倾向于做与你想做的相反的事情。我使我的域对象尽可能无知(它们本质上是财产包)。当您需要执行某种操作(例如发送电子邮件)时,我会为此使用服务并让该方法获取执行操作所需的域对象。在这种情况下,您只需将服务注入应用程序的各个部分(使用 Ninject 更容易实现)。

    【讨论】:

    • 有点离题:“财产袋”令人担忧。这意味着您有创建贫血域的危险。非常离题:酷头像=)
    • 我看到了双方的利益(并且在某种程度上双方都争论过)。我确实倾向于在对象中保留简单的验证,所以从这个意义上说,我猜它们不是严格意义上的属性包,但如果一个对象足够复杂,放置业务逻辑会很快使类膨胀,并且很快就会超过 1000 行代码(我已经看到它发生了很多)。当我想到“业务逻辑”这个词时,我倾向于想到一系列复杂的规则,如果是这样的话,我更喜欢一个单独的类,如果它只是验证,那么把它放在类中似乎是合理的。永远喜欢黑魔法师!
    • +1。我做的完全一样;我让我的 POCO 几乎没有逻辑(除了非常简单的 setter 验证)。像发送电子邮件这样的问题确实属于服务层。将服务注入域对象似乎违反直觉,IMO。
    • 我回应了第一条评论。如果您的域对象是属性包,那么它们更像是域 DTO,而不是域对象。谷歌“贫血领域模型反模式”。此外,域服务并非旨在成为域逻辑的默认位置。这违背了领域对象封装业务逻辑的目的。
    • 你可以抛弃“贫血的数据模型”之类的术语,引用 Fowler 之类的人的话,但归根结底,我见过更成功的系统编写的复杂业务逻辑包含在模型之外,然后是系统,所有这些都被破坏在一起并且难以维护。任何系统的真正价值在于它为用户服务的好坏,而不是它是否遵循各种编程原则。我不是反原则,但就我而言,现实世界的情景总是胜过理论。
    【解决方案3】:

    我认为 EF 代码优先 CTP 5 可能会有所帮助。它尊重 IValidatableObject 接口,该接口将 ValidationContext 对象作为参数。 ValidationContext 是一个 ServiceLocator,因此您应该能够使用 validationContext 对象获取 IoC 容器的实例。 (这只是我最初的想法,虽然我没有尝试过任何东西)。对不起,如果我的英语不是很懂。

    更新 抱歉,在我发布此评论后,我意识到这个问题与我所理解的完全不同。所以,我自己确实尝试了一些东西,经过一些尝试和尝试以及更多的谷歌搜索,我能够到达某个地方。我打算在这里发布答案,但后来考虑反对它,因为答案会很长。所以,我确实发布了这个博客。

    http://nripendra-newa.blogspot.com/2011/02/entity-framework-ctp5-injecting-with.html

    这可能会帮助一些搜索相同内容的谷歌用户。希望我这次答对了。

    【讨论】:

      猜你喜欢
      • 2011-06-15
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      • 2011-11-18
      • 1970-01-01
      • 1970-01-01
      • 2013-08-26
      • 1970-01-01
      相关资源
      最近更新 更多