5

ModelStateDictionaryにラッパーがあり、すべてのサービスがこれを受け入れます。コントローラーModelStateDictionaryをラッパーのコンストラクターに挿入してからサービスコンストラクターに挿入するようにautofacを構成することは可能ですか?

//code
public class ModelValidation : IModelValidation { 
public ModelValidation(ModelStateDictionary msd){...}
..
..
}

public class CustomerService{
public CustomerService(IModelValidation mv){...}
..
}

ありがとう

4

3 に答える 3

9

あなたのコメントに基づいて、私はここに私の答えを修正します:)

ModelStateDictionaryコンテナによって解決されるべきサービスではなく、インスタンス化時に提供されるべきデータであることは明らかです。ModelState は各 Controller インスタンスによって所有されているため、「解決時」にコンテナーで使用できないという事実からわかります。

さらに、各ModelValidationインスタンスはインスタンスにバインドされるため、データModelStateDictionaryとも見なされます

Autofac では、データを (オプションで他の依存関係に加えて) コンストラクターに渡す必要がある場合、ファクトリ デリゲートを使用する必要があります。これらのデリゲートは、コンストラクターへの依存関係とデータの受け渡しを処理します。Autofac の優れた点は、これらのデリゲートを自動生成できることです。

次の解決策を提案します。

ModelValidation と CustomerService の両方がコンストラクターでデータを必要とするため、2 つのファクトリ デリゲートが必要です (注: パラメーター名は、対応するコンストラクターの名前と一致する必要があります)。

public delegate IModelValidation ModelValidationFactory(ModelStateDictionary msd);
public delegate CustomerService CustomerServiceFactory(ModelStateDictionary msd);

コントローラーはこれらのデリゲートがどこから来たのかを知る必要がないため、依存関係としてコントローラー コンストラクターに渡す必要があります。

public class EditCustomerController : Controller
{
    private readonly CustomerService _customerService;

    public EditCustomerController(CustomerServiceFactory customerServiceFactory
        /*, ...any other dependencies required by the controller */
          )
    {
        _customerService = customerServiceFactory(this.ModelState);
    }

}

CustomerService には、これに似たコンストラクターが必要です (オプションで、この一部を ServiceBase クラスで処理します)。

public class CustomerService
{
    private readonly IModelValidation _modelValidation;

    public CustomerService(ModelStateDictionary msd,
              ModelValidationFactory modelValidationFactory)
    {
        _modelValidation = modelValidationFactory(msd);
    }

これを実現するには、次のようにコンテナを構築する必要があります。

var builder = new ContainerBuilder();

builder.Register<ModelValidation>().As<IModelValidation>().FactoryScoped();
builder.Register<CustomerService>().FactoryScoped();

builder.RegisterGeneratedFactory<ModelValidationFactory>();
builder.RegisterGeneratedFactory<CustomerServiceFactory>();

builder.Register<EditCustomerController>().FactoryScoped();

そのため、コントローラーが解決されると ( MvcIntegration モジュールを使用する場合など)、ファクトリー デリゲートがコントローラーとサービスに注入されます。

更新: 必要なコードをさらに削減するには、ここでCustomerServiceFactory説明したような一般的なファクトリ デリゲートに置き換えることができます。

于 2009-12-01T12:28:47.310 に答える
1
Builder.RegisterInstance(new ModelStateDictionary()).SingleInstance();
            builder.Register(c => new SW.PL.Util.ModelStateWrapper
(c.Resolve<ModelStateDictionary>())).As<IValidationDictionary>().InstancePerHttpRequest(); 
于 2012-03-10T17:36:38.260 に答える
0

ValidationService なしで新しいコンストラクターを追加します。プロパティを使用して ValidationService を割り当てます。

プロパティは、インターフェイス ICosumerService で実装する必要があります

public class ModelStateWrapper: IValidationDictionary {  
public ModelStateWrapper(ModelStateDictionary msd){}
}

public class CustomerService: ICostumerService{
public IValidationDictionary ValidationDictionary { get; set; }
public CustomerService(ICustomerRepsitory customerRepository, IValidationDictionary validationDictionary ){} 
public CustomerService(ICustomerRepsitory customerRepository){}
}

public Controller(ICustomerService customerService)
{
  _customerService= menuService;
  _customerService.ValidationDictionary = new ModelStateWrapper(this.ModelState);
  _customerService= sportsService;
}
于 2010-10-01T20:37:42.280 に答える