簡體   English   中英

注冊通用工廠

[英]Register generic factory

我有一個ICommandICommandHandler<TCommand>接口,需要注入工廠:

public class CommandProcessor
{
    private readonly Func<Type, ICommandHandler<ICommand>> _handler;

    public CommandProcessor(Func<Type, ICommandHandler<ICommand>> handler)
    {
        _handler = handler;
    }
}

能夠執行以下操作:

public void Process(ICommand command)
{
    var handler = _handler(command.GetType());

    if (handler != null)
    {
        handler.Handle(command);
    }

    throw ...
}

我試着注冊工廠:

    builder.Register<Func<Type, ICommandHandler<ICommand>>>(context => type =>
        {
            var handlerType = context.Resolve(type);
            return (ICommandHandler<ICommand>) handlerType;
        });

但得到以下異常:

請求的服務“QVocado.Commands.Information.PostProblemCommentCommand”尚未注冊。 要避免此異常,請注冊組件以提供服務,使用IsRegistered()檢查服務注冊,或使用ResolveOptional()方法解析可選依賴項。

在我看來,你的CommandProcessor只是你系統中一個無用的抽象。 讓他們直接依賴於ICommandHandler<TCommand>接口的一個或多個封閉版本,而不是讓消費者依賴CommandProcessor 這可以優雅地解決您的問題,因為Autofac可以為您解決這些依賴關系。 此外,這可以防止將對象/依賴關系圖分解為子圖(這是使用工廠時會發生的情況),這使得驗證DI配置變得更加容易。

也許你引入CommandProcessor抽象的原因是因為否則你必須向許多消費者注入許多ICommandHandler<TCommand>依賴。 在這種情況下,您可能違反了單一責任原則 ,這導致難以維護且難以測試的類。

刪除CommandProcessor還消除了在每條命令消息上實現ICommand的需要。

請注意,您注冊的委托不會解析命令處理程序,而只是解析命令。 您將使用MakeGenericType創建ICommandHandler<TCommand>接口的封閉通用版本來執行此操作。 這是正確的實現:

builder.Register<Func<Type, ICommandHandler<ICommand>>>(
    context => commandType =>
    {
        var handlerType = typeof(ICommandHandler<>)
            .MakeGenericType(commandType);
        var handler = context.Resolve(handlerType);
        return (ICommandHandler<ICommand>)handler;
    });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM