1

Autoface を使用して新しい MVC4 サイトを作成しています。このサイトには、一般消費者向けサイトと、消費者向けサイトを管理するための管理領域があります。管理サイトは、消費者向けサイトと同じサービスを使用して別の場所に配置されますが、カスタム ブランド機能の一部はありません。

ビューが使用する共有データのセットを提供する ViewDataFactory を使用するという他の場所でのアドバイスに従いました。私の目標は、あなたがいるエリアに応じて異なる ViewDataFactory を提供することです。

たとえば、IViewDataFactory を実装するサービスは次のとおりです。

builder.RegisterType<SelfServiceViewDataFactory>().As<IViewDataFactory>();

これにより、すべてのコントローラーに挿入される 1 つの ViewFactory が得られます。ただし、私が達成しようとしているのは、次のようなものです(機能コードではありません):

builder.RegisterType<ViewDataFactory>().As<IViewDataFactory>().ForType(ControllerBase1);    
builder.RegisterType<DifferentViewDataFactory>().As<IViewDataFactory>().ForType(ControllerBase2);    

コントローラーのタイプまたは MVC 領域によって、解決されるサービスが決定される場所。

編集

私の投稿を明確にするために、2 つの質問があります。

  1. Autofac で「タイプ X のクラスに対してのみ、タイプ Y のサービスがインスタンス Z によって提供される」と言う方法はありますか?
  2. コンポーネントが使用されているエリアに基づいて Autofac の動作を変更する方法はありますか?

私が読んできたすべてのことから、どのコンポーネントを提供するかを確認するために使用するパラメーターがない限り、#1への答えは「いいえ」のようです。Ninject は名前空間に基づいて依存関係を提供できることを知っているので、他のフレームワークがこのケースを処理しているようです。解決策は、パラメーターを指定するか、2 つの異なるサービスを定義することです。

Autofac と MVC の分野についてはあまり議論されていないので、#2 もカスタム ソリューションなしでは不可能だと思います。ありがとう!

4

1 に答える 1

2

名前付きサービスを使用するのがおそらく最良の選択肢です。したがって、次のようにします。

builder
    .RegisterType<ViewDataFactory>()
    .Named<IViewDataFactory>("Area1");    

builder
    .RegisterType<DifferentViewDataFactory>()
    .As<IViewDataFactory>("Area2");

そして、コントローラーを手動で登録する必要を避けたい場合。私がまとめただけでテストしていないこのコードを使用できます。

この属性をグローバルにアクセス可能な場所に配置します。

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
public class ServiceNamedAttribute : Attribute
{
    private readonly string _key;

    public ServiceNamedAttribute(string key)
    {
        _key = key;
    }

    public string Key { get { return _key; } }
}

このモジュールを Autofac 構成に追加します。

public class ServiceNamedModule : Module
{
    protected override void AttachToComponentRegistration(
        IComponentRegistry registry, IComponentRegistration registration)
    {
        registration.Preparing +=
            (sender, args) =>
            {
                if (!(args.Component.Activator is ReflectionActivator))
                    return;

                var namedParameter = new ResolvedParameter(
                    (p, c) => GetCustomAttribute<ServiceNamedAttribute>(p) != null,
                    (p, c) => c.ResolveNamed(GetCustomAttribute<ServiceNamedAttribute>(p).Name, p.ParameterType));

                args.Parameters = args.Parameters.Union(new[] { namedParameter });
            };
    }

    private static T GetCustomAttribute<T>(ParameterInfo parameter) where T : Attribute
    {
        return parameter.GetCustomAttributes(typeof(T), false).Cast<T>().SingleOrDefault();
    }
}

そして、コンストラクターを次のように装飾することで、コントローラーを自動登録できます。

public class Controller1
{
    public Controller1(ServiceNamed["Area1"] IViewDataFactory factory)
    { ... }
}
于 2013-01-02T15:52:11.993 に答える