1

OpenGenericICommandHandlerのTに基づいてkeyedServiceを作成したいと思います。ICommandHandlerにConsultantCommandから継承するTがある場合、ConsultatCommandHanlderキー付きサービスを登録したいと思います。

それを行う方法はありますか?またはそれが可能であるならば?私はAutoFacを初めて使用し、苦労しています。

私は現在、次のようにCommandHandlerを登録しています。

        //Register All Command Handlers
        builder.RegisterAssemblyTypes(assemblies)
          .As(
              t =>
              t.GetInterfaces()
               .Where(a => a.IsClosedTypeOf(typeof (ICommandHandler<>)))
               .Select(a => new KeyedService("commandHandler", a))).InstancePerHttpRequest();

可能であれば、Closed Typeを取得するときにCommandHandlerを識別し、何らかの方法でCommandがConsultantCommandを実装しているものを識別する必要があると思います。

私は試した:

        builder.RegisterAssemblyTypes(assemblies)
               .As(
                 t =>
                   t.GetInterfaces()
                    .Where(a => a.IsClosedTypeOf(typeof(ICommandHandler<>)) &&
                        a.GetGenericArguments()[0].IsSubclassOf(typeof(ConsultantCommand)))
                    .Select(a => new KeyedService("ConsultantCommandHandler", a))).InstancePerHttpRequest();

しかし、喜びはうまくいかないようです。コンパイルされますが、ConsultantCommandから継承するものであってもCommandHandlerは登録されません。私の構文はすべて間違っていると思います

4

2 に答える 2

1

あなたが欲しい:

builder.RegisterAssemblyTypes(assemblies)
       .AsClosedTypesOf(typeof(ICommandHandler<>))
       .AsSelf()
       .AsImplementedInterfaces()
       .InstancePerHttpRequest();
于 2012-11-30T14:12:48.987 に答える
1

ICommandHandler<T>まず、共分散をサポートするように宣言されていることを確認する必要があります。

public interface ICommandHandler<out T> { }

これは重要です。そうしないと、すべてのハンドラーを一度outに解決できなくなります。ConsultantCommandAutofac例外も発生します。

次に、Namedextensionメソッドを使用して、自分で行うのではなく、名前付きサービスを登録します。構文は次のようになります。

builder.RegisterAssemblyTypes(assemblies)
       .Where(t =>
                t.IsClosedTypeOf(typeof(ICommandHandler<>)) &&
                t.GetInterfaces()[0]
                 .GetGenericArguments()[0]
                 .IsAssignableTo<ConsultantCommand>())
       .Named("name", typeof(ICommandHandler<ConsultantCommand>))
       .InstancePerHttpRequest();

ICommandHandler<T>これは、Tから派生するすべてのサービスをとして登録しConsultantCommandますICommandHandler<ConsultantCommand>。基本タイプを使用する必要があります。そうしないと、すべてのハンドラーを一度に解決できなくなります。「この基本タイプから派生するすべてのサービスを解決する」方法はありません。オープンジェネリックのリストを解決する方法もありません。

IEnumerable<T>ハンドラーのリストを解決するときは、名前付き:を解決する必要があります。

using(var scope = container.BeginLifetimeScope())
{
  var x =
    scope.ResolveNamed<IEnumerable<ICommandHandler<ConsultantCommand>>>("name");
}

もちろん、使用してInstancePerHttpRequestいるので、次のようになります。

var x =
  AutofacDependencyResolver
    .Current
    .RequestLifetimeScope
    .ResolveNamed<IEnumerable<ICommandHandler<ConsultantCommand>>>("name");

上記のように、これは機能しないため、クローズドジェネリックとして登録する必要があります。

// WON'T WORK:
scope.ResolveNamed<IEnumerable<ICommandHandler<>>>("name");

必要に応じて登録などを変更できます。RegisterAssemblyTypes残りの登録拡張機能は通常どおり機能するはずです。実装されたインターフェイスなどとして登録する場合は、単一のサービスで行っているのと同じように機能するはずです。

于 2012-11-30T17:41:17.567 に答える