Is Ninject creating 2 separate context? - c#

I'm creating a Web API and I'm using dependency inject wit Ninject.
I have:
IRTWRepository
IModelFactory
I'm injecting those 2 into my controllers like this.
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IRTWRepository>().To<RTWRepository>();
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>();
kernel.Bind<IModelFactory>().To<ModelFactory>();
}
My RTWRepository constructor looks like this
public class RTWRepository :IRTWRepository
{
private RTWAPIContext _context;
public RTWRepository(RTWAPIContext context)
{
_context = context;
}}
My ModelFactory constructor looks like this
public class ModelFactory : IModelFactory
{
private IRTWRepository _repo;
public ModelFactory(IRTWRepository repo)
{
_repo = repo;
}
}
I have a Controller that looks like this:
public MaterialsController(IRTWRepository repository,IModelFactory modelFactory)
: base(repository,modelFactory)
{
}
Now, my question is : Is Ninject creating 2 separate contexts when creating an instance of my RTWRepository and also when creating an instance of ModelFactory?.
The reason that I'm asking that is because I'm having a problem when I try to save an entity that has a dependency to another object which was previously retrieve from the db.
I'm saving the entity in my controller but I'm creating it in my model factory along with is dependency.
public class RecycleCenter
{
public RecycleCenter()
{
}
public int MyProperty { get; set; }
[Required]
public virtual Address Address { get; set; }
}
The code above is for the entity Recycle Center which has an Address, this recycle center entity is created in my model factory and then in my controller I try to save it but when my repository execute this line
_context.RecycleCenters.Add(entity);
I'm getting this error
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
So, somewhere in my code I'm using 2 context instead of 1 and I think is when creating the ModelFactory and RTWRepository, is this assumption correct?, if so how do I fix it?

TL;DR;
You probably need to change this line:
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>();
to
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InRequestContext();
Explanation:
When you define a binding in Ninject, you also specify how that object's lifecycle should be handled.
If you don't explicitly define it, Ninject's default lifecycle is Transient. Transient means that each time an instance is required, it will create a new one. In your case, you need to two instances: one for the RTWRepository of the ModelFactory and one for the RTWRepository of the MaterialsController.
You can modify the lifestyle to one of these options:
Singleton ==> kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InSingleTonScope();
Request ==> kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InRequestScope();
Thread ==> kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InThreadScope();
Named, Call, Parent, Custom
In your case, I think you need InRequestScope, but you have to check the necessary lifecycle as it depends on the application.
For further information please check out the documentation here: https://github.com/ninject/ninject/wiki/Object-Scopes

Most probably, it is. There's no annotation that is telling to Ninject "Hey, stop, when you have created the instance once, reuse it". You should agree that in most cases, you would want multiple instances of an object and that it is a rare case, where you want it only once.
If you want to reuse the instance, use the singleton pattern. Ninject is familiar with it, so you can bind the object mapping to a method
kernel.Bind<RTWAPIContext>().ToMethod(c => RTWAPIContext.GetInstance());
There is also a ToSingleton binding, but I bet you cannot make your context constructor private and implement C# specific singleton due to other ASP.NET problems (e.g. ASP.NET Identity will try to invoke the context's method for object creation).

Related

How to determine which constructor Autofac uses when resolving

I'm using a custom JsonConverter and JsonSerializerSettings.TypeNameHandling = TypeNameHandling.Objects to create the required instances during deserialization. The instances are created by resolving the types from an Autofac IOC container. Everything works fine, except...
I have several "core objects" that request a unique Id in the constructor from a service (which is correctly injected into the constructor). When deserializing this should not happen because it is fairly expensive and the Ids will be populated from the Json file anyway once the instance has been created.
Currently, when resolving from within the custom JsonConverter I'm using _scope.Resolve<T>(new TypedParameter(typeof(IIdService), null)); to then - in the called constructor - check for null and act accordingly.
Some people apparently consider multiple constructors worse than a code-smell when using an IOC (which makes me wonder why Autofac offers several features regarding the topic), but in the context of deserialization I think it can make perfect sense.
As far as I can tell Autofac has mechanisms to decide which constructor to use during registration, but not when resolving. My preferred solution would be to add a custom attribute to a constructor (e.g. [CtorForDeserializing]) and use that for deciding. Is that possible?
There are a couple of extension points Autofac has for reflection-based activations but doesn't have well documented yet that may help you out: IConstructorFinder and IConstructorSelector.
IConstructorFinder is used to locate all the available constructors on a type. The core example is the DefaultConstructorFinder which locates only public constructors. If you wanted to, say, hide constructors with particular attributes or start finding internal/private constructors, you could create a custom finder. This really only happens once so you don't get to make runtime choices here.
IConstructorSelector is used to choose, at resolve time, which constructor should be used to instantiate the object. There are a couple of these in core Autofac, but the primary example is the MostParametersConstructorSelector which selects the constructor that has the most available matching parameters at the time. Constructors get found by the IConstructorFinder and then that set of constructors is what is presented to the IConstructorSelector to choose from. This is where you could make more runtime choices since it happens every time the object is resolved.
There are extension methods to help you add your finder/selector to a registration:
builder.RegisterType<MyType>()
.FindConstructorsWith(new MyConstructorFinder())
.UsingConstructor(new MyConstructorSelector());
You don't have to customize both things, you can just do one or the other if you want. I'm just showing you the extensions.
Actually Autofac is able to decide which constructor to use both ways - during registration or resolution. For resolution part here is the quote from documentation: "Autofac automatically uses the constructor for your class with the most parameters that are able to be obtained from the container" (see here).
Consider following example.
public interface ISomeService
{
Guid Id { get; }
}
public class SomeService : ISomeService
{
public Guid Id { get; }
public SomeService()
{
Id = Guid.NewGuid();
}
public SomeService(Guid id)
{
Id = id;
}
}
// Startup.cs:
builder.RegisterType<SomeService>().As<ISomeService>().InstancePerLifetimeScope();
// TestController.cs:
[Route("api/[controller]")]
public class TestController : Controller
{
private readonly IComponentContext _context;
public TestController(IComponentContext context)
{
_context = context;
}
[HttpGet]
public IActionResult Get()
{
var service = _context.Resolve<ISomeService>();
return Ok(service.Id);
}
[HttpGet("{id}")]
public IActionResult Get(Guid id)
{
var service = _context.Resolve<ISomeService>(new NamedParameter("id", id));
return Ok(service.Id);
}
}
// GET http://localhost:5000/api/test/e0198f72-6337-4880-b608-68935122cdea
// each and every response will be the same: e0198f72-6337-4880-b608-68935122cdea
// GET http://localhost:5000/api/test
// this way it responds with some random guid each time endpoint is called
Travis Illig sent me in the right direction - thanks!
I ended up implementing a solution around the following details:
Implement custom attributes, e.g.: public class DeserializeCtorAttribute : Attribute { }, which will be used by the (also to be implemented) IConstructorFinder.
Implement an empty generic interface, e.g.: IDeserializable<T>, which will be used for resolving the services/components.
Let relevant component classes implement the interface (MyClass : IDeserializable<MyClass>) and add an extra registration for the component:
_builder.RegisterType<MyClass>().As<IDeserializable<MyClass>>()
.FindConstructorsWith(MyConstructorFinder);
Use the implemented DeserializeCtorAttribute in the desired constructor of MyClass.
Let the JsonConverter create the required instance by calling (MyClass) scope.Resolve(IDeserializable<MyClass>); casting is required, but safe. Due to the registration the instance will be created using the desired constructor.

Dependency Injection with Ninject share same objects with different instances

I've been gifted having had to work with an already set up Ninject DI based application which I have grown and added to considerably over the development of an application I'm working on.
I now find a problem that I would like to correct. I've managed to work around it using inheritance but would like a more cleaner solution.
I have two connections required to be injected into different services and repositories. I then need the repositories to also be correctly linked to the correct service having the same UnitOfWork.
I think I might be asking something that is not possible without inheritance and specialisation but that is why I am asking.
I managed to resolve this by creating a sub class of the main Repository and UnitOfWork classes but does nothing apart from implementing the base class.
I just don't like the idea of a sub class that is fully dependant on the super class functionality with basically empty braces apart from constructor, to me this doesn't seem true OOP just to resolve this problem. So I sought for a better solution utilising a one class solution if possible in DI.
So if you can ignore the solution I have spoken about because I completely reverted the change this is what I am left with:
Looking at the code below you can see what is the objective.
...
public class UnitOfWork : IUnitOfWork
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger("UnitOfWork");
public DbContext DataContext { get; set; }
public UnitOfWork(string connectionString)
{
DataContext = new DbContext(connectionString);
}
public void Commit()
{
...
}
}
...
public class Repository<T> : IRepository<T> where T : class
{
public IUnitOfWork unitOfWork { get; set; }
private readonly IDbSet<T> dbSet;
//private static readonly log4net.ILog log = log4net.LogManager.GetLogger("Repository");
public Repository(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
dbSet = this.unitOfWork.DataContext.Set<T>();
}
...
}
...
public class IPOPDataModules : NinjectModule
{
public override void Load()
{
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["IPOP_BE_TESTEntities"].ConnectionString);
Bind<IRepository<tOrder>>().To<Repository<tOrder>>().InRequestScope();
}
}
...
public class DataModules : NinjectModule
{
public override void Load()
{
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["IPOP_BAPSEntities"].ConnectionString);
Bind<IRepository<Data.Quote>>().To<Repository<Data.Quote>>().InRequestScope();
}
}
...
public class QuoteService : IQuoteService
{
private IUnitOfWork unitOfWork;
private IRepository<Data.Quote> quoteRepository;
public QuoteService(IUnitOfWork unitOfWork, IRepository<Data.Quote> quoteRepository)
{
...
}
}
...
public class IPOPService : IIPOPService
{
private IUnitOfWork unitOfWork;
private IRepository<Data.tOrder> tOrderRepository;
public IPOPService(IUnitOfWork unitOfWork, IRepository<Data.tOrder>)
{
...
}
}
What I want to know is, is it possible to share the same UnitOfWork and Repository objects by two different connections and have them injected as different instances to the respective services (IPOPService for IPOP_BE_TEST connection, QuoteService for IPOP_BAP connection)
Again the code above doesn't achieve want I want but this is the sort of architecture I would like to play around to get this to work.
What you're looking for are Ninject binding scopes. Whenever you declare a binding Ninject will provide a delegate to that binding that the activation process uses to determine if it should create a new instance of that service, or if it should return a previously constructed instance.
So, if you want to implement a singleton in Ninject, you simply declare a binding that looks like this:
Bind<IRepository<Data.Quote>>().To<Repository<Data.Quote>>().InSingletonScope();
InSingletonScope() and InRequestScope() are simply sugar (or in the case of InRequestScope an extension method) on IBindingInSyntax<T> for the InScope(Func<Ninject.Activation.IContext, object> scope) method though. Any time you want to ensure that Ninject returns the same instance of a service in a given situation, all you need to do is implement a custom scope.
If I understand your question correctly, you want to ensure that when a request hits your application the same instances of Repository<T> and IUnitOfWork will be injected into all the services in your application. In this case you would simply have to write bindings like this:
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["IPOP_BE_TESTEntities"].ConnectionString);
Bind<IRepository<tOrder>>().To<Repository<tOrder>>().InRequestScope();
However, your problem appears to be that you have two separate modules, with two separate bindings. I would suggest that you need to use a single module with contextual binding to determine which connection string should be provided to which part of the system. So your one module might look like this:
Bind<IUnitOfWork>()
.To<UnitOfWork>()
.WhenInjectedInto<IIPOPService>()
.InRequestScope()
.WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["IPOP_BE_TESTEntities"].ConnectionString);
Bind<IUnitOfWork>()
.To<UnitOfWork>()
.WhenInjectedInto<IQuoteService>()
.InRequestScope()
.WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["IPOP_BAPSEntities"].ConnectionString);
Bind<IRepository<tOrder>>().To<Repository<tOrder>>().InRequestScope();
This way you can be sure that when Ninject is resolving IIPOPService it will create an instance of UnitOfWork initialized with the "IPOP_BE_TESTEntities" connection string, and when resolving IQuoteService, it will use the "IPOP_BAPSEntities" connection string, but otherwise, across that request scope, only a single instance will be constructed by Ninject.
Hope this helps.
Your question is not completely clear for me. But check the documentation for the following two scopes, which might be interesting for your scenario.
InCallScope will result that only one instance will be created per resolution tree. I usually use this scope on desktop applications for a unit of work. See the documentation here. You'll need the Ninject.Extensions.NamedScope extension for this.
InRequestScope will result that in a web application, only one instance will be created per HTTP request. I usually use this scope for a unit of work. See the documentation here. You'll need the Ninject.Web.Common package for this.

Autofac Property Inject issues

I am using MVC with EF and Autofac. I have a concrete class called Helper. Helper is in another DLL and not the main MVC web application.
It has a property of type DBContext called 'Context'.
I want to inject an instance of the DBContext into this property - however its always null.
Here is what I have so far in GLobal:
var output = new DbContext(connectionString);
builder.RegisterInstance(output).As<DbContext>().PropertiesAutowired();
builder.RegisterType<Helper().WithParameter("Context",output).PropertiesAutowired();
// Set the dependency resolver to be Autofac.
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
Context is the property on the Helper class which I would like injected with the instance 'output'.
Context is always null.
In Autofac, the easiest way to manage dependencies is to leverage constructor injection.
Basically, instead of telling Autofac "wire up the properties for me and do your mojo", you tell him to let YOU in charge of declaring the list of components.
So, instead of wondering why property injection is not working, declare explicitly your dependencies in Helper constructor:
public class Helper
{
public DbContext Context { get; private set; }
public Helper(DbContext context /* Autofac is going to fill in this */)
{
Context = context;
}
}
Then, in Global (or in some other class encapsulating your registrations) you just tell Autofac to look at the Helper type and try his best to call the best constructor, which is the simplest thing you can do:
// Either InstancePerDependency, or SingleInstance, or something else depending upon you requirements.
builder.RegisterType<Helper>().AsSelf().InstancePerDependency();
And you should be done: Autofac will search for the constructor with most parameters (and there will be only one with a parameter of type DbContext and will check if he knows how to create parameters for the requested type (which he can).
So, voilĂ , you get a ready to use Helper!
Edit: I'm keeping the example above, because it's the correct answer to the question, BUT, to reply to the comment, I would use a little more machinery, in the form of an Init method:
public class Helper
{
public DbContext Context { get; private set; }
public Init(DbContext context /* Autofac is going to fill in this */)
{
Context = context;
}
}
And you can instruct Autofac to call this method during object initialization:
builder.RegisterType<CustomHelper>()
.AsSelf()
.InstancePerDependency()
.OnActivating(h => {
var dbContext = h.Context.Resolve<DbContext>();
((Helper)h.Instance).Init(dbContext);
});
OnActivating lets you write the explicit initialization call. Keep in mind you probably want to register all the types in an assembly which derive from Helper, but probably that is for another question.

Object sharing and dynamic instance creation

I've a base class for business logic operations that is being inherited by my co-worker. This class expose a constructor which requires an objectContext as parameter. You can think of this base class as a component for atomic CRUD operations (all its select, insert, edit and delete method will always act on just one entity).
Then, I have a "super class" which its primary purpose is shared the objectContext between all the above base class in order to execute some business transaction and also it must provide any baseClass instance, if required.
So, I'm looking for to elegant way to "inject" superClass's objectContext into a baseclass:
public BaseClass<T> where T : entity
{
private ObjectContext _ctx;
public BaseClass(ObjectContext ctx){ _ctx = ctx;}
public virtual IList<T> Select(){..}
public cirtual voind Insert(T entity){..}
// other stuff
}
public class SuperClass
{
private ObjectContext _ctx = new...
public BaseClass<TEntity> LoadBaseClass(TBase, TEntity) where TBase : BaseClass<TEntity>, where TEntity : class
{
BaseClass<TEntity> obj = Activator.CreateInstance(typeof(TBase), _ctx); // share objectContext
}
public int SaveAll(){return _ctx.SaveChanges();}
}
As you can see, my super class is able to return some baseClass instance through its type and it's just what I want. However, if some inherited class defines its own contructor with other parameter my LoadBaseClass method will fails.
I would find a clean solution in order to avoid any kind of possibility of error during instance creations from LoadBaseClass method. The only way I know is to define a private contructor, but by this way no-one will be able to inherit baseclass anymore..
What you are looking for is called Dependency Injection. You are now trying to build this by hand but there are a lot of tools that already do what you want.
Dependency Injection is all about constructing objects and configuring how and when those objects are created. It comes down to splitting object creation from your business logic.
In your case, you are working with something called the Unit Of Work and Repository pattern. Using a Dependency Injection container like Ninject you can easily configure your UnitOfWork to be shared between all repositories like this:
var kernel = new StandardKernel();
kernel.Bind<IMyRepository>().To<ConcreteRepository();
kernel.Bind<IMyUnitOfWork>().To<ObjectContextImp>().InRequestScope();
IMyRepository repos = kernel.Get<IMyRepository>();
What Ninject (or any DI tool) will do is try to construct a IMyRepository. You've configured it to look for a ConcreteRepository. Then it notices that the ConcreteRepository takes a IMyUnitOfWork in its constructor. In this case you have mapped this to your ObjectContextIml and added the InRequestScope option.
InRequestScope is for ASP.NET web applications and it means that your context should be created once for each request. Ninject has a couple of different Object Scopes that you can use to configure how your object should be created and shared.
This way, you have complete control over how your objects are created.

DI: Associating entities with repository

I'm pretty new to the concept. What I'm trying to do is create a factory that will return an object that is used for repository functions. No problems there. So I create the instance of a concrete factory in main() and store it in a static property of App but my entities are in a separate dll. Does it make sense to pass the repository to each entity class in the constructor? This doesn't feel right. My question is: how is the best make my entities aware of which repository they should be using?
My App partial class looks like
public partial class App : Application
{
private static ICalDataAccess _daqFactory;
public static ICalDataAccess DataAccessFactory
{
set { _daqFactory = value; }
get { return _daqFactory; }
}
}
Maybe a little more code is in order.
public class Widget
{
public string Description { get; set; }
public int ID { get; set; }
private IWidgetRepository _widgetRepository;
public Widget(IWidgetRepository WidgetRepository)
{
_widgetRepository = WidgetRepository;
}
public void Save()
{
_widgetRepository.Save(this);
}
}
Am I doing anything egregious here?
I think the general recommendation is to keep your entities free from persistence concerns. That is, you have some code that retrieves the entities and uses them to perform whatever work needs to be done, resulting in new, deleted or modified entities, which the calling code then submits to the appropriate repository (or asks to be saved if you have something which tracks or detects modified entities, like EF or NHibernate).
That way your entities do not need to know about repositories at all.
I usually create a UnitOfWork helper class which exposes all of my repositories through a "public RepositoryFactory Repositories { get; }" property, so that simply by supplying an instance of the UnitOfWork class I have access to all of my data sources. UnitOfWork can then be injected via IoC to whatever class needs to have data access.
Some recommended reading on this topic:
Persistence Patterns
Discussion on this same topic elsewhere
Your description sounds more like the service locator pattern than dependency injection. Dependency injection typically looks like any object that needs some service object (such as data access) to do its work receives that service as parameter to its constructor.

Categories