【问题标题】:When using an IoC container, how to pass dynamic data / objects to a class?使用 IoC 容器时,如何将动态数据/对象传递给类?
【发布时间】:2011-11-28 13:01:42
【问题描述】:

我有一个带有以下构造函数的 Order 类

public Order(IProduct product, short count)
{
this._product = product;
this._count = count;
}

我正在尝试设置 Unity IoC 容器,显然要构建订单对象,我需要知道计数和产品,但这些是在运行时确定的;计数可以是任何值,产品可以是任何产品,例如胡萝卜、甜瓜等

那么如何为此应用 IoC?

我认为的一种方法是我的构造函数只接受对象依赖项,然后使用新的 Initialize() 方法添加任何其他必需的属性:

public Order (IProduct product)
{
this._product = product;
}

public Initialize(short count)
{
this._count = count;
}

这样,无论谁创建 Order 对象,之后都必须调用 Initialize() 方法,以便将 IoC 容器无法处理的其他属性添加到其中。

这是您推荐/使用的方法吗?

【问题讨论】:

  • 不完全是,他们确实在 MyIntFactory 类中引入了新级别的依赖关系: public MyIntfFactory : IMyIntfFactory { public IMyIntf Create(string runTimeParam) { return new MyIntf(runTimeParam); } }
  • 我很惊讶为什么人们会提高这个答案,因为整个想法是对象实例化不应该发生在应用程序内部,而是来自 Unity,而这种方法只会增加新的复杂性并违反它。跨度>
  • 你可能想参考这个讨论:stackoverflow.com/questions/4835046/…
  • @William,对象实例化发生在整个应用程序中。 “更新”您的实体并不是您试图通过 DI 避免的。 Count 是一个整数,而不是依赖项。

标签: c# asp.net inversion-of-control unity-container ioc-container


【解决方案1】:

使用 Unity,您应该能够设置一个 ParameterOverride 来传递您的额外参数:

container.Resolve<IOrder>(new ParameterOverrides { { "Count", 1 } });

好的,或者创建一个工厂类:

class OrderFactory : IOrderFactory
{
    public OrderFactory ( IProduct product );
    public Order GetOrder (count)
    {
        return new Order ( product, count );
    }
}

使用容器解析工厂。然后使用工厂解决您的订单。

【讨论】:

  • 我更喜欢我的方法;在应用程序类中使用容器会很丑。
  • 经过一番思考后,我必须同意@William 的观点——上面的代码需要知道 IOrder 和 Order,这在某种程度上违背了 IoC/DI 的部分观点。您的应用不应该知道具体的 Order,因为它是在运行时注入的。查看blog.janjonas.net/2011-07-03/…的xml配置@
  • 第二个例子也应该真正使用抽象工厂。已经使它实现了一个接口以使这一点更加清晰。容器被设置为解析这个工厂。容器不需要知道订单。应用程序不需要知道任何一个具体的实现。
  • Err,有没有其他人注意到明显的 IoC 违规,new OrderGetOrder 中创建?
【解决方案2】:

@scottm 这是我在我的 aspx 页面中的实际代码:

private IStoresRankingReportPresenter _presenter;

     protected void Page_Init(object sender, EventArgs e)
            {
                this._presenter = ServiceLocator.Current.GetInstance<IStoresRankingReportPresenter>();

                this._presenter.Initialize(this, this.Count);

                this._presenter.OnPageInit();
            }

【讨论】:

    【解决方案3】:

    对我来说,这似乎不适合 IoC 容器。据推测,订单可以在应用程序的整个生命周期中根据用户的行为定期用不同的产品(和计数)实例化,这表明需要为每个可能创建订单的上下文配置一个容器——也就是说,对于每个产品页面。

    IoC 容器在您很少且在早期(例如在应用程序启动时)做出有关依赖关系的决定时效果最佳。如果决定注入哪个依赖项总是在创建依赖对象的同时进行,那么 IoC 容器只会增加不必要的复杂性。

    【讨论】:

    • 别忘了目的;使课程可测试。所以 IoC 容器对我来说只是我初始化依赖项的地方。
    • @William,DI 的目的不是使类可测试,这只是附带的好处。目的是减少耦合,促进扩展。
    【解决方案4】:

    Count 应该只是 Order 的一个属性。计数代表什么?订单行数还是产品数量?我不太确定您打算如何在这里实施 IoC 容器。

    类似这样的:

    public class Order
    {
      private IProduct _product;
      public Order(IProduct product)
      {
        _product = product;
      }
    
      public int Count {get;set;}
    }
    

    【讨论】:

    • imagine Count 是 IoC 容器无法确定其值的任何属性,但它是 Order 类工作的必备属性。
    • @William,你能说明你是如何注册和解决订单和产品的吗?
    • 我正在使用 asp.net 网络表单并使用 MVP。我的依赖关系在页面级别解决并传递给演示者。我使用的名称与 Order 和 Product 非常不同;在这里使用它们是为了简单抱歉,但关键是如何管理无法从 IoC 注入的此类必须依赖项。
    猜你喜欢
    • 2015-09-29
    • 1970-01-01
    • 2021-06-25
    • 1970-01-01
    • 2021-04-28
    • 2015-04-11
    • 1970-01-01
    • 2014-03-16
    • 2018-11-21
    相关资源
    最近更新 更多