3

コマンド ハンドラーで Handle メソッドの呼び出しをインターセプトしようとしています。このプロセスは、各コマンド ハンドラーを明示的に登録すると正常に機能します。問題は、コマンド ハンドラーとインターセプターの一般的な登録が正しくないことです。

例外:

タイプ 'Castle.MicroKernel.ComponentActivator.ComponentActivatorException' の例外が Castle.Windsor.dll で発生しましたが、ユーザー コードで処理されませんでした

追加情報: ComponentActivator: TempSearch.Command.Data.CommandHandlers.AddTempsJobCommandHandler をプロキシできませんでした

一部のコンポーネントが正しく構成されていないと表示されているため、インターセプターが見つからないようです。

「このコンポーネントの一部の依存関係を静的に解決できませんでした。\r\n'TempSearch.Command.Data.CommandHandlers.AddTempsCandidateAvailabilityCommandHandler' は次の依存関係を待機しています:\r\n- コンポーネント 'TempSearch.Ioc.ExceptionHandlingIntercepter' (オーバーライドを介して) ) が見つかりませんでした。登録するのを忘れたか、名前のつづりを間違えましたか? コンポーネントが登録されていて、タイプによる上書きである場合は、デフォルト以外の名前が明示的に割り当てられていないことを確認するか、名前による依存関係を上書きしてください。\r\ん」

インターフェース:

public interface ICommandHandler<TCommand>
{
    void Handle(TCommand command);
}

コマンドハンドラの例:

public class AddTempsCandidateAvailabilityCommandHandler 
    : ICommandHandler<TempsCandidateAvailability>
{
    private readonly IDbConnection connection;

    public AddTempsCandidateAvailabilityCommandHandler(
        IDbConnection connection)
    {
        this.connection = connection;
    }

    public void Handle(TempsCandidateAvailability command)
    {
        // ...
    }
}

登録:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Register(
        Component.For<IDbConnection>()
            .UsingFactoryMethod(() => ConnectionHelper.GetOpenDbConnection(
                Connection.DatabaseName.ReedOnline))
            .LifestylePerWebRequest());

    container.Register(
        Classes
            .FromAssemblyContaining<EcruiterCommands>()
            .Where(t => t.Name.EndsWith("Commands"))
            .WithService
            .AllInterfaces().LifestylePerWebRequest());

    container.Register(
        Classes
            .FromAssemblyContaining<EcruiterCommands>()
            .Where(t => t.Name.EndsWith("CommandHandler"))
            .WithService.AllInterfaces()
            .LifestylePerWebRequest()
            .Configure(c => c.Interceptors<ExceptionHandlingIntercepter>()
                .LifestyleTransient()));
}

インターセプター:

[Transient]
public class ExceptionHandlingIntercepter : IInterceptor
{
    private static readonly MethodInfo Execute = 
        typeof(ICommandHandler<>).GetMethod("Handle");

    private readonly IKernel kernel;

    public ExceptionHandlingIntercepter(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public void Intercept(IInvocation invocation)
    {
        if (invocation.Method != Execute)
        {
            invocation.Proceed();
            return;
        }

        try
        {
            invocation.Proceed();
        }
        finally
        {
            kernel.ReleaseComponent(invocation.Proxy);
        }
    }
}
4

2 に答える 2

6

コマンド ハンドラーを初期化するときに Castle がインターセプターを解決できるようにするには、インターセプター自体を登録する必要があります。以下を登録に追加します。

container.Register(
    Component.For<ExceptionHandlingIntercepter>(); // should be enough

インターセプターに名前を付けて名前で登録するのが好きです(理由はわかりません。あなたの方法はうまくいくはずです)

于 2015-04-15T10:06:04.833 に答える
0

このコードを使用してこれを修正しました:

public void Install(IWindsorContainer container, IConfigurationStore store)
        {    
            container.Register(
                Component.For<IInterceptor>()
                    .ImplementedBy<ExceptionHandlingIntercepter>().LifestyleTransient(),
                Classes
                    .FromAssemblyContaining<EcruiterCommands>()
                    .Where(t => t.Name.EndsWith("CommandHandler"))
                    .WithServiceAllInterfaces()
                    .LifestylePerWebRequest().Configure(c => c.Interceptors<ExceptionHandlingIntercepter>())
                );
        }
于 2015-04-15T15:10:05.463 に答える