如何在带参数的简单注入器中实现工厂接口

How to implement Factory Interface in Simple Injector With Parameters

This answer 展示了如何使用不带参数的工厂接口解析实例。

我正在使用以下代码

public interface ISimpleBarFactory 
{
   Bar CreateBar(int value);
}

public sealed class SimpleBarFactory : ISimpleBarFactory 
{
    private readonly Container _container;
    public SimpleBarFactory (Container container)
    {
        _container = container;
    }

    public Bar CreateBar(int value) 
    {
       _container.Register(() => new Bar(vlue));
       return _container.GetInstance<Bar>();
    }
}

解析具有构造函数参数的实例。

但是,在使用工厂实例化服务时出现以下异常class:

The container can't be changed after the first call to GetInstance, GetAllInstances and Verify.

使用带参数的工厂接口解析实例的正确方法是什么?

更新

以下是我的代码。我正在从 Ninject.

迁移代码
public interface IFormsUIFactory
{
   AccountUI CreateAccountUI(Account account);
}

public class FormsUIFactory
{
    private readonly IFormsUIFactory _uiFactory;
    public FormsUIFactory(IFormsUIFactory uiFactory)
    {
        _uiFactory = uiFactory;
    }

    public void CreateAccountUI(Account account)
    {
        _uiFactory.CreateAccountUI(account);
    }
}

UI class 待注入

public partial class AccountUI : Form
{
    private readonly IAccountMaintenanceProcessor _processor;
    private readonly Account _account;
    public AccountUI(IAccountMaintenanceProcessor accountProcessor, Account account)
    {      
        _processor = accountProcessor;
        _account = account;
    }

 }

实例化代码:

var account = new Account();
// Populate values for the account

var frm = _uiFactory.CreateAccountUI(account);

您遇到的问题是由于您将运行时数据(您的Account)对象与组件混合在一起。您的 DI 容器负责构建组件的对象图。这些组件通常应该是无状态的,运行时数据应该使用方法调用流经对象图。在组件的构造函数中注入运行时数据,使这些组件具有状态,并以许多不同的方式使您的应用程序复杂化;您今天正在目睹这些并发症之一。但是这样做有很多缺点。例如,将运行时数据注入构造函数使得无法验证您的对象图(使用自动化测试)并使您的应用程序很容易在运行时中断。所以这绝不是 Simple Injector 特定的,但 Simple 确实通过在解析服务时不允许传递运行时值来使问题更加突出。 你可以找到关于这个的详细解释 here.

因此,请尽量让您的组件保持无状态,并且至少让运行时数据远离构造函数。实现此目的的一种简单方法是将 属性 添加到允许设置您正在使用的实体的表单。可以将通用界面添加到表单以允许这样做:

interface IForm<TEntity>
{
    TEntity Entity { get; set; }
}

此通用接口可用于 IFormFactory 抽象:

interface IFormFactory
{
    TForm CreateFormFor<TForm, TEntity>(TEntity entity) 
        where TForm : Form, IForm<TEntity>;
}

IFormFactory 创建一个实现就这么简单:

public class FormFactory : IFormFactory
{
    private readonly Container container;

    public FormFactory(Container container) {
        this.container = container;
    }

    public TForm CreateFormFor<TForm, TEntity>(TEntity entity) 
        where TForm : Form, IForm<TEntity> {
        var form = this.container.GetInstance<TForm>();
        form.Entity = entity;
        return form;
    }
}