c# - Register generic factory -
i have icommand
, icommandhandler<tcommand>
interfaces , need inject factory:
public class commandprocessor { private readonly func<type, icommandhandler<icommand>> _handler; public commandprocessor(func<type, icommandhandler<icommand>> handler) { _handler = handler; } }
to have ability following:
public void process(icommand command) { var handler = _handler(command.gettype()); if (handler != null) { handler.handle(command); } throw ... }
i tried register factory:
builder.register<func<type, icommandhandler<icommand>>>(context => type => { var handlertype = context.resolve(type); return (icommandhandler<icommand>) handlertype; });
but got following exception:
the requested service 'qvocado.commands.information.postproblemcommentcommand' has not been registered. avoid exception, either register component provide service, check service registration using isregistered(), or use resolveoptional() method resolve optional dependency.
seems me commandprocessor
useless abstraction in system. instead of letting consumer depend on commandprocessor
, let them depend directly on 1 or multiple closed versions of icommandhandler<tcommand>
interface. solves problem elegantly, because autofac can resolve dependencies you. besides, prevents breaking object/dependency graph sub graphs (which happens when use factory) , makes easier verify di configuration.
perhaps reason introduced commandprocessor
abstraction because otherwise have inject many icommandhandler<tcommand>
dependencies consumers. in case violating single responsibility principle , leads classes hard maintain , hard test.
removing commandprocessor
removes need implement icommand
on each command message.
note delegate registered not resolves command handler, command. have create closed generic version of icommandhandler<tcommand>
interface using makegenerictype
this. here proper implementation:
builder.register<func<type, icommandhandler<icommand>>>( context => commandtype => { var handlertype = typeof(icommandhandler<>) .makegenerictype(commandtype); var handler = context.resolve(handlertype); return (icommandhandler<icommand>)handler; });
Comments
Post a Comment