web-dev-qa-db-ja.com

AutoFacを使用してインターフェースを自動的にバインドする

UserQuery、CustomerQueryのようないくつかのクラスがあり、それぞれIUserQuery、ICustomerQueryのようなインターフェイスを実装しています。バインディング構成では、すべてのインターフェイスをそれぞれのクエリでバインドする必要があります。

builder.RegisterType<UserQuery>().As<IUserQuery>().InstancePerRequest();
builder.RegisterType<CustomerQuery>().As<ICustomerQuery>().InstancePerRequest();

これはかなりうまく機能していますが、すべてのクラスXXX [Query]-> [I] XXX [Query]をバインドする代わりに、規則ベースのバインドを作成する方法があるかどうか疑問に思いました。

私はDIコンテナとしてAutoFacを使用しています。

20
user2011100

私はAutoFacの経験豊富なユーザーではありません。ただし、いくつかの調査の後、以下のコードをテストして成功しました。

var Assembly = Assembly.GetExecutingAssembly();

builder
    .RegisterAssemblyTypes(Assembly)
    .AssignableTo<IQuery>()
    .AsImplementedInterfaces()
    .InstancePerRequest();

上記のIQueryインターフェイスは、使用しているすべてのクエリインターフェイスから継承する必要がある単なるタグインターフェイスです。あなたの例を使用して:

インターフェイス

IUserQuery: IQuery
ICustomerQuery: IQuery

クラス

UserQuery: IUserQuery
CustomerQuery: CustomerQuery
30

Autofacの アセンブリスキャン機能 を使用する必要があります。

インターフェイスまたは実装が基本クラス(例:QueryBase)または基本インターフェイス(例:IQuery)を共有している場合は、次のような説得力のあるメソッドを使用して登録できます。_AssignableTo<>_ 、などを参照してください gustavodidomenico's 回答。

ただし、共通のベースインターフェイス/クラスを使用できない場合もあります。その場合は、Whereメソッドを使用して、登録するクラスとその方法を検出するためのカスタムロジックを使用できます。

その場合、登録はおおよそ次のようになります。

_builder.RegisterAssemblyTypes(yourAssembly)
       .Where(t => t.IsClass && t.Name.EndsWith("Query"))
       .As(t => t.GetInterfaces().Single(i => i.Name.EndsWith(t.Name)));
_

名前が_"Query"_で終わる特定のアセンブリのすべてのタイプを一致するインターフェイスに登録するため、SomeNiceQueryをインターフェイスISomeNiceQueryに登録します。

10
nemesv

または、各タイプを最初に実装されたインターフェイスまたは独自のインターフェイスとして登録することもできます。

builder.RegisterAssemblyTypes(new[] { Assembly.GetAssembly(typeof(IUserQuery))})
        .Where(x=> x.IsClass && x.Name.EndsWith("Query"))
        .As(t => t.GetInterfaces().Any() ? t.GetInterfaces()[0] : t);
0
arviman