Change ServiceOverride after component registration in Castle -
i have 2 components registered service:
container.register( component.for<idatastorage>().named("firstchoice").implementedby... component.for<idatastorage>().named("secondchoice").implementedby then have set of components deriving base class, depends on components:
public abstract class basemessagehandler { public idatastorage firststorage {get; set;} public idatastorage secondstorage {get; set;} } if registering these "handlers" (deriving basemessagehandler) manually, specify service override, indicating component want properties "firststorage" , "secondstorage". like:
.configure(x => x.dependson( serviceoverride.forkey("firststorage").eq("firstchoice"), serviceoverride.forkey("secondstorage").eq("secondchoice")) unfortunately, registration done automatically framework (nservicebus). know if register handlers first (before nservicebus has chance so), these registrations stick. rather try guess , mimick registration nservicebus does, wonder if can specify service overrides in custom icontributecomponentmodelconstruction. seems place so, , i'm able find these properties:
public class datastorageoverridecontributor : icontributecomponentmodelconstruction { public void processmodel(castle.microkernel.ikernel kernel, castle.core.componentmodel model) { var datastoragedependencies = model.properties.where( x => x.dependency.targetitemtype == typeof(idatastorage)); foreach (var propertydependency in datastoragedependencies) { // what?? but i'm not sure proper way to:
- check if service override specified (in case nothing)
- add service override property dependency.
is done inspecting , working componentmodel in icontributecomponentmodelconstruction.processmodel method?
i use subdependency resolver in scenario. can see code below on how use it.
goodluck,
marwijn.
public interface idatastorage { }
public class datastore1 : idatastorage { } public class datastore2 : idatastorage { } public class basemessagehandler { public idatastorage firststorage { get; set; } public idatastorage secondstorage { get; set; } } public class subdependencyresolver : isubdependencyresolver { private readonly ikernel _kernel; public subdependencyresolver(ikernel kernel) { _kernel = kernel; } public bool canresolve(creationcontext context, isubdependencyresolver contexthandlerresolver, componentmodel model, dependencymodel dependency) { return model.implementation == typeof (basemessagehandler) && dependency.targettype == typeof(idatastorage); } public object resolve(creationcontext context, isubdependencyresolver contexthandlerresolver, componentmodel model, dependencymodel dependency) { var handlers = _kernel.gethandlers(dependency.targettype); switch (dependency.dependencykey) { case "firststorage": return handlers.single(h => h.componentmodel.implementation == typeof (datastore1)).resolve(context); case "secondstorage": return handlers.single(h => h.componentmodel.implementation == typeof(datastore2)).resolve(context); } return null; } } [testfixture] public class tests { [test] public void sometest() { var container = new windsorcontainer(); container.kernel.resolver.addsubresolver(new subdependencyresolver(container.kernel)); container.register( component.for<idatastorage>().named("firstchoice").implementedby<datastore1>(), component.for<idatastorage>().named("secondchoice").implementedby<datastore2>(), component.for<basemessagehandler>() ); var messagehandler = container.resolve<basemessagehandler>(); assert.areequal(typeof(datastore1), messagehandler.firststorage.gettype()); assert.areequal(typeof(datastore2), messagehandler.secondstorage.gettype()); } } alternative may use:
case "firststorage": return handlers.single(h => h.componentmodel.name == "firstchoice").resolve(context); case "secondstorage": return handlers.single(h => h.componentmodel.name == "secondchoice").resolve(context); to resolve on component name rather implementation type.
Comments
Post a Comment