[英]Register generic factory
我有一個ICommand
和ICommandHandler<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.