I am trying to separate reads/writes in my MVC application. I am using Simple Injector as Ioc and I have following structure:
new Service(
new Repository(
new UnitOfWork(
new DbContext())))
So UnitOfWork
registered per web request all the rest Transient
.
So idea was to create separate read-only controllers and make a registration of DbContext
to supply a different connection if controller is read-only. And that could be achievable with improved RegisterWithContext extension BUT it will not work in my case because not all graph nodes are Transient
.
Is there any way (more elegant than register each Repository with improved RegisterWithContext extension where need to supply another read-only UnitOfWork
and manually resolve all other arguments that passed into Repository
) how the described scenario can be achieved?
Since the choice is based on the type of controller, you can make the descision in a custom IControllerFactory
. For instance:
public class ConnectionSelector {
public bool AsReadOnly { get; set; }
}
private class ReadOnlySwitchControllerFactory : DefaultControllerFactory {
private readonly Container container;
public ReadOnlySwitchControllerFactory(Container container) {
this.container = container;
}
protected override IController GetControllerInstance(RequestContext requestContext,
Type controllerType) {
var selector = this.container.GetInstance<ConnectionSelector>();
selector.AsReadOnly =
typeof(IReadOnlyController).IsAssignableFrom(controllerType);
return base.GetControllerInstance(requestContext, controllerType);
}
}
You can register this as follows:
container.RegisterPerWebRequest<ConnectionSelector>();
container.RegisterPerWebRequest<DbContext>(() => new DbContext(
container.GetInstance<ConnectionSelector>().AsReadOnly
? "ReadOnlyConnection"
: "NormalConnection"));
container.RegisterSingle<IControllerFactory>(
new ReadOnlySwitchControllerFactory(container));