c# - Create instance using ctor injection and ServiceProvider -
i know there iservicecollection
interface can register services , iserviceprovider
can instantiate services.
how instantiate class, based on specified type, uses registered services?
class myclass { public myclass(isomeservice someservice) { } } var servicecollection = new servicecollection(); servicecollection.addsingleton<isomeservice, someservice>() myclass instance = createinstance(typeof(myclass)); object createintance(type type) { ??? }
for example, how asp.net core creates controller instances?
i've made naive implementation of activator isn't there in .net core already?
private static object createinstance(type type, iserviceprovider serviceprovider) { var ctor = type.getconstructors() .where(c => c.ispublic) .orderbydescending(c => c.getparameters().length) .firstordefault() ?? throw new invalidoperationexception($"no suitable contructor found on type '{type}'"); var injectionservices = ctor.getparameters() .select(p => serviceprovider.getrequiredservice(p.parametertype)) .toarray(); return ctor.invoke(injectionservices); }
}
edit: scenario. i've refactored legacy code implements interface.
public interface ieventdispatcher { void registerhandler(type handler); void dispatch(domainevent @event); }
in dispatch method implementation create instances of handlers:
public class inmemorybus : ieventdispatcher { private readonly list<type> _handlers = new list<type>(); private readonly func<type, object> activator; /// <param name="activator">used create instance of message handlers</param> public inmemorybus(func<type, object> activator) { this.activator = activator; } public void dispatch(domainevent @event) { type messagetype = message.gettype(); var openinterface = typeof(ihandlemessages<>); var closedinterface = openinterface.makegenerictype(messagetype); var handlerstonotify = h in _handlers closedinterface.gettypeinfo().isassignablefrom(h.gettypeinfo()) select h; foreach (type h in _handlerstonotify) { //this tricky part var handlerinstance = activator(h); closedinterface.gettypeinfo() .getmethod(nameof(ihandlemessages<t>.handle)) .invoke(handlerinstance, new[] { message }); } } public void registerhandler(type type) => _handlers.add(type); }
given
public class myclass { public myclass(isomeservice someservice) { //... } }
you need build entire object graph provider knows can create
var servicecollection = new servicecollection(); servicecollection.addsingleton<isomeservice, someservice>() servicecollection.addtransient<myclass>(); iserviceprovider provider = servicecollection.buildserviceprovider(); myclass instance = provider.getservice<myclass>();
when provider.getservice<myclass>()
called provider initialize myclass
, resolving dependencies in process.
Comments
Post a Comment