Resolve dependency by ninject "ToProvider" method, which is based on HttpContext.Current - c#

I have layered asp.net MVC application. My application has following architecture:
DomainLayer, which contains domain objects
DAL (repository pattern), has reference only to DomainLayer
BLL, has reference to DomainLayer and DAL
PresentationLayer(Web), has reference to DamainLayer and BLL
And I have separate layer(let's call it DependencyResolver), which is responsible for resolving dependencies through all application layers. I use Ninject dependency resolver. This project has references to DomainLayer, DAL and BLL
I need to resolve dependencies of some object in different ways based on logged user role. For example I have 2 implementations of the same IOrderRepository: OrderSQLRepository and OrderMemoryRepository:
For UserRole.Admin I have to call
Bind<IOrderRepository>().To<OrderSQLRepository>();
And for other users I need to bind interface to IOrderMemoryRepository which accepts the Session as constructor argument, to store values temporary in session.
Bind<IOrderRepository>().To<OrderMemoryRepository>().WithConstructorArgument("pSession", HttpContext.Current.Session);
So as there is conditional case, I use ToProvider method:
Bind<IOrderRepository>().ToProvider<OrderRepositoryProvider>();
public class OrderRepositoryProvider : IProvider
{
public Type Type { get { return typeof(IOrderRepository); } }
public object Create(IContext context)
{
if (HttpContext.Current.User.IsInRole("Admin"))
{
return context.Kernel.Get<OrderMemoryRepository>(new ConstructorArgument("pSession", HttpContext.Current.Session["Orders"]));
}
return context.Kernel.Get<OrderSQLRepository>();
}
}
But as the bindings are perforemed in separate project, which does not have reference to System.Web.Mvc namespace, I couldn't use HttpContext.Current.
So what would you suggest, am I in right direction or should I use different approach or if the direction is right, how can I pass the HttpContext.Current to Load() method of NinjectModule or to OrderRepositoryProvider

You are on the right track, however, typically in a web application the web layer is the composition root (contains all your bindings) because it is the entry point into the app. in other words, put all your bindings into the web layer as NinjectModules.
Additionally, you may consider creating wrappers for the HttpContext values you want to use. for example, IHttpContext that implements a getter for HttpContext.Current.User and then use the interface in your provider instead of the concrete HttpContext.Current. I would do the same for retrieving the orders from session, i.e., ISessionOrders and then Ninject would be able to resolve the dependency for OrderMemoryRepository without a constructor argument.
so then you would have:
public object Create(IContext context)
{
if (context.Kernel.Get<IHttpContext>().User.IsInRole("Admin"))
{
return context.Kernel.Get<OrderMemoryRepository>();
}
return context.Kernel.Get<OrderSQLRepository>();
}

Related

Resolve Dependency on a repository interface MVC5 using structuremap

I have a mapper that takes data from a repository project. I have a IMenueMapper interface that is passed into the homecontroller like this:
public HomeController(IMenueMapper menueMapper)
{
_menueMapper = menueMapper;
}
but the menuemapper class itself use the IMenueMapperRepository, and this come from another project and is passed in via dll
public MenueMapper(IMenueItemsRepository menueItems)
{
_menueItems = menueItems;
}
While I can easily resolve the IMenuemapper in the MVC project, using structuremap.mvc5, I can't resolve the repository. Is there a way of achieving the DI in this instance?
You need to register the abstraction (repository interface and implementation) in the composition root.
You indicated that the IMenueMapper is registered via;
scan.AssemblyContainingType<MenueMapper>();
Since
but the MenueMapper class itself use the IMenueMapperRepository, and
this come from another project and is passed in via dll
Then it should also be scanned as it belongs to another assembly
scan.AssemblyContainingType<MenueItemsRepository>();
Make sure that the project references the assembly in question

Where dependency-injection registrations have to be put?

I've read the question Ioc/DI - Why do I have to reference all layers/assemblies in application's entry point?
So, in a Asp.Net MVC5 solution, the composition root is in the MVC5 project (and having a DependencyInjection assembly in charge of all the registrations does not make sense).
Within this picture, it is not clear to me what is the better approach among the following.
Approach 1
The concrete implementations are public class ... and all registrations clauses are centralized within the composition root (e.g. in one or more files under a CompositionRoot folder). MVC5 project must reference all the assemblies providing at least one concrete implementation to be bound. No library references the DI library. MVC project can contain interfaces to be bound with no drawbacks.
Approach 2
The concrete implementations are internal class .... Each library exposes a DI 'local' configuration handler. For example
public class DependencyInjectionConfig {
public static void Configure(Container container) {
//here registration of assembly-provided implementations
//...
}
}
which is up to register its own implementations. The composition root triggers registrations by calling all the Configure() methods, just one for each project. MVC5 project must then reference all the assemblies providing at least one concrete implementation to be bound. Libraries must reference the DI library. In this case, the MVC5 project cannot contain interfaces (otherwise there would be a circular reference): a ServiceLayer assembly would be needed to hold public interfaces to be bound.
Approach 3
Same as Approach 2, but local configuration modules are discovered dynamically through assembly reflection (by convention?). So MVC5 project has not to reference libraries. MVC project can contain interfaces and can be referenced by libraries. Libraries must reference the DI library.
What is the best practice here? Is there some other better possibility?
EDIT 1 (2016-12-22)
Thanks to received answers, I published this github project describing the best solution I found so far.
EDIT 2 (2018-09-09)
This answer provides an interesting option.
EDIT 3 (2020-12-29)
Finally, I came up with a complete solution, packaged in the form of a WebApi application template. I published this solution on GitHub HERE. This approach, not only gives a clear understanding about where DI rules have to be put, but also suggests to setup the application according to SOLID principles and CQRS pattern. The commit history of this project has been structured to have educational purposes.
EDIT 4 (2023-01-31)
The repository linked above publishes an article describing the solution as well.
I typically like to encapsulate these types of things into each project. So for example I might have the following. (This is an extremely simplified example, and I'll use the AutoFac in this example, but I'd imagine all DI frameworks have something like the following).
Common area for just POCOs and Interfaces.
// MyProject.Data.csproj
namespace MyProject.Data
{
public Interface IPersonRepository
{
Person Get();
}
public class Person
{
}
}
Implementation of Repositories and Data Access
// MyProject.Data.EF.csproj
// This project uses EF to implement that data
namespace MyProject.Data.EF
{
// internal, because I don't want anyone to actually create this class
internal class PersonRepository : IPersonRepository
{
Person Get()
{ // implementation }
}
public class Registration : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register<PersonRepository>()
.As<IPersonRepository>()
.IntancePerLifetimeScope();
}
}
}
Consumer
// MyPrject.Web.UI.csproj
// This project requires an IPersonRepository
namespace MyProject.Web.UI
{
// Asp.Net MVC Example
internal class IoCConfig
{
public static void Start()
{
var builder = new ContainerBuilder();
var assemblies = BuildManager.GetReferencedAssemblies()
.Cast<Assembly>();
builder.RegisterAssemblyModules(assemblies);
}
}
}
So the Dependencies look like:
MyProject.Data.csproj
- None
MyProject.Data.EF.csproj
- MyProject.Data
MyProject.Web.UI.csproj
- MyProject.Data
- MyProject.Data.EF
In this setup, the Web.UI cannot know anything about what is registered nor for what reason. It only knows that the EF project has implementations but can't access them.
I can drop EF for say Dapper extremely easily as each project encapsulates it's own implementations and registration.
If I was adding unit tests and had an InMemoryPersonRepository, how would I swap out the PersonRepository for my InMemoryPersonRepository?
Assuming we ignore any business logic layer and have an MVC Controller directly access our Data Accessor, my code might look like:
public class MyController
{
private readonly IPersonRepository _repo;
public MyController(IPersonRepository repo)
{
_repo = repo;
}
public IActionResult Index()
{
var person = _repo.Get();
var model = Map<PersonVM>(person);
return View(model);
}
}
Then a test using nSubstitute Might look like:
public class MyControllerTests
{
public void Index_Executed_ReturnsObjectWithSameId
{
// Assign
var repo = Substitute.For<IPersonRepository>();
var expectedId = 1;
repo.Get().Returns(new Person { Id = expected });
var controller = new MyController(repo);
// Act
var result = controller.Index() as ActionResult<PersonVM>;
// Assert
Assert.That(expectedId, Is.EqualTo(result.Value.Id));
}
You've identified a real problem. (One could say it's a good problem to have.) If entry application Areferences B, B references C, and B and/or C require some DI registration, that makes A (your entry application) responsible for knowing enough about the details of B and C to register all the dependencies.
The solution is to have a separate assembly that handles composing all of the registrations for B and C. A references that, and it provides all of the container configuration that A needs to use B and C.
The benefits are
A doesn't know more about B and C than it should
Neither A, B, nor C have to be tied to one particular DI framework like Unity or Windsor.
Here's an example. This is an event bus class that works best with a DI container. But in order to use it you shouldn't have to know all about the dependencies it needs to register. So for Windsor I created a DomainEventFacility. You just call
_container.AddFacility<DomainEventFacility>();
and all of the dependencies are registered. The only thing you register are your event handlers.
Then if I want to use the same event bus library with a different DI container like Unity I can just create some similar assembly to handle the same configuration for Unity.

Unity Dependency Injection - How to create the instance to be injected at runtime

Trying to implement Dependency Injection in an ASP.Net Web API project.
I would like to be able to inject an instance of Account into some of my services.
The Account instance should be created with the users Guid and this is not known until runtime.
So in my service I have:
public TransactionService(Account acc)
{
_account = acc;
}
And in my application startup I can do this - where container is a new UnityContainer:
container.RegisterType<Instanet.Engine.Account>(new InjectionConstructor(new Guid("xxxxxx")));
This, of course, isn't any good as it would be using the same Account for every user/request etc.
If I try to use something like :
container.RegisterType<Instanet.Engine.Account>(new InjectionConstructor(GetTheUsersID()));
... where GetTheUsersID() needs to either examine a cookie or the ASP.Net Identity request it's of course not available in the app startup.
So - Where/How (in simple terms please, this DI stuff is hurting my brain) do I implement this so I can inject an instanced Account into any of the services that may need it.
You generally don't want to mix state and behavior for components that get resolved via the container--DI should be used for components that can be modeled as pure services.
That said, sometimes it makes sense to wrap global or context-specific state in a service component.
In your case, if you only need the UserId locally in a one or more services (in other words, not passing it from one service to another). You mentioned being able to get the UserId from a cookie, so maybe it would look something like:
public class CookieService : ICookieService
{
public int GetCurrentUserId()
{
//pseudo code
return HttpContext.Current.GetCookie["UserId"];
}
}
Now you can inject ICookieService where a UserId is needed.
More complex cases may require an Abstract Factory:
http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/
If there is only one Account instance possible for the session, then I would create an Account instance in the bootstrap code before all your services are running.
Then you can populate the guid and all other data in your account instance, and register the initialized instance of Account class in Unity via container.RegisterInstance method.
Later it will resolve to what you need.
Does it help?

Injecting runtime value into Unity dependency resolver

I am working on a webapi project and using Unity as our IOC container. I have a set of layered dependencies something like the following:
unityContainer.RegisterType<BaseProvider, CaseProvider>(new HierarchicalLifetimeManager());
unityContainer.RegisterType<IRulesEngine, RulesEngine>();
unityContainer.RegisterType<IQuestionController, QuestionController>();
unityContainer.RegisterType<IAPIThing, WebAPIThing>();
Now the constructor for BaseProvider accepts an int as a parameter which is the Case identifier. WebAPIThing takes a BaseProvider in its constructor. Normally in a non web scenario I would inject the case id using something like:
public static IAPIThing GetIAPIThing(int caseId)
{
return CreateUnityContainer().Resolve<IAPIThing >(new ParameterOverride("caseId", caseId).OnType<CaseProvider>());
}
But that only works when I explicitly call that method. In a Web API scenario I am using a
config.DependencyResolver = new UnityDependencyResolver(unityContainer); to resolve my api controllers.
I would guess I will still need to influence how the DependencyResolver resolves that BaseProvider object at runtime.
Anyone had to do something similar?
EDIT 1
I have tried using the following which appears to work:
unityContainer.RegisterType<BaseProvider>(
new HierarchicalLifetimeManager()
, new InjectionFactory(x =>
new CaseProvider(SessionManager.GetCaseID())));
You are trying to inject a runtime value (the case id) into the object graph, which means you are complicating configuration, building, and verification of the object graph.
What you should do is promote that primitive value to its own abstraction. This might sound silly at first, but such abstraction will do a much better job in describing its functionality. In your case for instance, the abstraction should probably be named ICaseContext:
public interface ICaseContext
{
int CurrentCaseId { get; }
}
By hiding the int behind this abstraction we effectively:
Made the role of this int very explicit.
Removed any redundancy with any other values of type int that your application might need.
Delayed the resolving of this int till after the object graph has been built.
You can define this ICaseContext in a core layer of your application and everybody can depend on it. In your Web API project you can define a Web API-specific implementation of this ICaseContext abstraction. For instance:
public class WebApiCaseContext : ICaseContext
{
public int CurrentCaseId
{
get { return (int)HttpContext.Current.Session["CaseId"];
}
}
This implementation can be registered as follows:
unityContainer.RegisterType<ICaseContext, WebApiCaseContext>();
UPDATE
Do note that your own new CaseProvider(SessionManager.GetCaseID()) configuration does not solve all problems, because this means that there must be a session available when verifying the object graph, which will neither be the case during application startup and inside a unit/integration test.

IoC and ASP.NET MVC Controllers

Should I do something along the lines of this? I'm thinking of all my controllers inheriting from BaseController. Does this break the design pattern of IoC? What else should I do instead?
public class BaseController: Controller
{
protected ICookieService CookieService {
get {
return ServiceResolver.Resolve<ICookieService>(new { HttpContext = HttpContext });
}
}
protected IDateTimeService DateTimeService {
get {
return ServiceResolver.Resolve<IDateTimeService>();
}
}
protected ISettingsService SettingsService {
get {
return ServiceResolver.Resolve<ISettingsService>();
}
}
}
It would be a lot simpler to go with constructor injection and have a controllerfactory inject it for you. If you can, don't use a service locator (your ServiceResolver ) if you can get away with constructor injection.
There's some info on it on Adding a controller factory to ASP MVC
The link shows how to do it with StructureMap and it looks like you're using Unity, but it should be straightforward to adapt.
I'm assuming that the protected interfaces you have are dependencies for the controller. Its possible to set up an IoC container to inject the dependencies for you. It can certainly be done with Castle Windsor. You would need to change you BaseController class to have a constructor with the required dependencies, as long as the IoC container knows about the other services it'll be able to inject them.
One of the principles behind Inversion of Control and Component-Driven Development is about using static service locators only when there is no other way (i.e.: in web service hosts or object data sources).
Technically speaking, using static service locators the base controller does not violate IoC, it just does not use it.
Check out existing integration between Autofac IoC container and ASP.NET MVC (other containers should be able to do that as well).

Categories

Resources