Pass constructor with Ninject - c#

I have one base generic repository and many class repository that inherits from the base repository. I need too pass string value to the generic repository.
Here is my Generic Repository
public class Repository<T> where T : EntityBase
{
private string SessionId;
public Repository(string sessionId)
{
this.SessionId = sessionId;
}
protected virtual IDbConnection GetCn()
{
return new SqlConnection(ConfigurationManager.ConnectionStrings["SalesDb"].ConnectionString);
}
public virtual int Insert(T entity)
{
entity.ChUser = "anders.persson";
entity.ChTime = DateTime.Now;
using (IDbConnection cn = GetCn())
{
cn.Open();
return cn.Insert(entity);
}
}
// MORE CODE
}
}
And the interface
public interface IRepository<T>
{
int Insert(T entity);
}
My Class Repository
public class MarketRepository : Repository<Market>, IMarketRepository
{
}
And the interface
public interface IMarketRepository : IRepository<Market>
{
}
Now i want to pass sessionId to the Generic Repositories constructor.
How can i do that. In this case i have to implement a constructor in every class repository and pass it to the base repository. And the interface dont even know about that constructor.
Here is the Ninject bindings
private static void RegisterServices(IKernel kernel)
{
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
kernel.Bind<ILeadRepository>().To<LeadRepository>();
kernel.Bind<IPricelistRepository>().To<PricelistRepository>();
kernel.Bind<IOptionalGroupRepository>().To<OptionalGroupRepository>();
kernel.Bind<IProductGroupRepository>().To<ProductGroupRepository>();
kernel.Bind<IProductRepository>().To<ProductRepository>();
kernel.Bind<IMarketRepository>().To<MarketRepository>();
kernel.Bind<IModelRepository>().To<ModelRepository>();
kernel.Bind<IOrderRepository>().To<OrderRepository>();
}

You can add it to a binding:
Bind<IMarketRepository>().To<MarketRepository>().WithConstructorArgument("sessionId", "Session ID here");

The sessionId would be a runtime value, so you'll want to pass it to the ctor when resolving.
The syntax to do that is:
var reposetory
= kernel.Get<IMarketRepository>(new ConstructorArgument("sessionId", sessionId));
Given that you don't want to use a Service Locator, calling Get directly, and use ctor injection instead, you can encapsulate that inside a factory.
Configuration:
kernel.Bind<IRepositoryFactory>().To<RepositoryFactory>()
.WithConstructorArgument("kernel", kernel);
Factory:
public class RepositoryFactory : IRepositoryFactory
{
private IKernel _kernel;
public RepositoryFactory(IKernel kernel)
{
_kernel = kernel;
}
public T CreateNew<T>(string sessionId)
{
return
_kernel.Get<T>(new ConstructorArgument("sessionId", sessionId));
}
}
Usage:
var repository = _repositoryFactory.CreateNew<IMarketRepository>(sessionId);

Related

Can't add generic Interface to List with same constraint

I'm struggling with generics and don't really know what I'm doing wrong.
This is my example:
public class Repository // Base-class for all repositories
{
public virtual int GetStatus()
{
return 0;
}
}
Repository is just a base class.
public class CarRepository : Repository // base-class for all car repositories
{
private object dataSource;
public override int GetStatus()
{
return dataSource.GetHashCode(); // dummy
}
public virtual int GetPrice(string carName)
{
if (carName.Equals("BMW", StringComparison.OrdinalIgnoreCase)) {
return 100;
}
return 50;
}
}
CarRepository simply provides basic methods to interact with cars.
public class HttpCarRepository : CarRepository // loads the car data from REST Api
{
private dynamic httpClient; // just as an example
public override int GetStatus()
{
return httpClient.IsConnected();
}
public override int GetPrice(string carName)
{
return httpClient.GetAsync("/rest/car/BMW").Result;
}
}
There might also be an DataBaseCarRepository that loads the data from a database. You get the point.
That's for the setup.
Now, I want to cache the results. To keep it generic, I've created this construct:
public interface ICache<TRepo> // Basic Cache Interface
where TRepo : Repository
{
TRepo Repository { get; set; }
}
public class CarCache : CarRepository, ICache<CarRepository>
{
public CarRepository Repository { get; set; }
private dynamic cache;
public CarCache(CarRepository repo)
{
this.Repository = repo;
}
public override int GetPrice(string carName)
{
if (!this.cache.Contains(carName)) {
this.cache.Add(carName, this.Repository.GetPrice(carName));
}
return cache[carName];
}
}
CarCache derives from the base class CarRepository to make it possible to override the methods. It also implements ICache<T> which provides a reference to an actual
implementation of CarRepository, such as HttpCarRepository.
Now I want to add the CarCache to a list of caches.
public class Manager
{
public List<ICache<Repository>> Caches;
}
I've used Repository as the generic type because the ICache<T> interface constraints the type to Repository.
Now the problem:
I've got a method to add a cache that looks like this
static void Add<TCache>(Repository repo)
where TCache : Repository, ICache<TCache>
{
ICache<TCache> newEntry = Activator.CreateInstance(typeof(TCache), repo) as ICache<TCache>;
Caches.Add(newEntry); // Error: Cannot convert from ICache<TCache> to ICache<Repository>
}
That confuses me. From my understanding this should work because I've added the constraint where TCache : Repository to the method, so adding an item of that type
to a list of ICache<Repository> should work. It's the same constraint.
What's the problem here?
One solution would be to make ICache<TRepo> covariant.
You would need to make TRepo Repository get-only to comply with covariant restrictions:
public interface ICache<out TRepo> where TRepo : Repository
{
TRepo Repository { get; }
}
This would work fine as long as the property is only set via your constructor:
public class CarCache : CarRepository, ICache<CarRepository>
{
public CarRepository Repository { get; }
public CarCache(CarRepository repo)
{
this.Repository = repo; // Fine to set Repository here
}
// ...
}
Or you could make the setter private to allow other methods of the implementation class to set the value:
public class CarCache : CarRepository, ICache<CarRepository>
{
public CarRepository Repository { get; private set; }
// ...
void SetRepository(CarRepository repo)
{
this.Repository = repo;
}
}

Unity with the same interface, multiple factories

So the issue, is when I declare:
[Dependency]
public AuthenticationService _authenticationServices { get; set; }
The _authenticationServices will constantly remain null. It isn't referenced, which will throw a Null Reference Exception. I'm assuming the issue stems from my Unity Configuration file:
container.RegisterType<ICrudFactory, ZNodeDataContextFactory>();
container.RegisterType<ICrudFactory, MincronDataContextFactory>();
Since they both use the same interface, but a separate concrete implementation. The implementation is as follows:
public interface ICrud : IDisposable
{
// Method's to be exposed, via general repository.
}
public interface ICrudFactory
{
ICrud Create();
}
public ZNodeDataContext : DbContext, ICrud
{
// Concrete implementation.
}
public MincronDataContext : DbContext, ICrud
{
// Concrete implementation.
}
public ZNodeDataContextFactory : ICrudFactory
{
ICrud ICrudFactory.Create()
{
return ZNodeDataContext();
}
}
public MincronDataContextFactory : ICrudFactory
{
ICrud ICrudFactory.Create()
{
return MincronDataContext();
}
}
public class AuthenticationService
{
private readonly ICrudFactory _factory;
public AuthenticationService(ICrudFactory factory)
{
_factory = factory;
}
public void Sample()
{
using(var context = _factory.Create())
context.Method(...);
}
}
I'd like to keep that structure, to avoid code duplication.
Do you want to inject ZNodeDataContextFactory into AuthenticationService ? A bit of the point with the injection is that the service should not now anything about the implementation. But if you really want a specific implementation you can create a named instance.
public class AuthenticationService
{
private readonly ICrudFactory _factory;
public AuthenticationService([Dependency("ZNodeData")] ICrudFactory factory)
{
_factory = factory;
}
}
And in your configuration:
container.RegisterType<ICrudFactory, ZNodeDataContextFactory>("ZNodeData");
container.RegisterType<ICrudFactory, MincronDataContextFactory>("MincronData");
Alternatively:
public class AuthenticationService
{
private readonly IEnumerable<ICrudFactory> _factories;
public AuthenticationService(ICrudFactory[] factories)
{
// Now you got both...
_factories = factories;
var zNodeFactory = _factories.FirstOrDefault(x => x.Factory == ZNode);
}
}
public interface ICrudFactory
{
ICrud Create();
// Something to identify the type of data. Maybe an enum?
FactoryType Factory {get;}
}
public ZNodeDataContextFactory : ICrudFactory
{
ICrud ICrudFactory.Create()
{
return ZNodeDataContext();
}
FactoryType ICrudFactory.Factory
{
{get {return FactoryType.ZNode;}
}
}
I ended up solving the issue, by creating particular containers for each generic repository.
public interface IZNodeContextFactory : ICrudFactory
{
}
public interface IMincronContextFactory : ICrudFactory
{
}
By doing it in this manner, I was able to simply do:
container.RegisterType<IZNodeContextFactory, ZNodeContextFactory>();
container.RegisterType<IMincronContextFactory, MincronContextFactory>();
This allowed the automatic dependency resolver to work, and implement since they now had unique names.

Can MEF resolve a Func delegate returning an interface?

Code at bottom is from a working WPF sample application that used Autofac for dependency injection.
I want to convert to latest version of MEF instead. I also have NuGet packages CommonServiceLocator (V. 1.3) and Prism.Core, Prism.Mef and Prism.Wpf (all 6.1) installed.
When I do
var provider = ServiceLocator.Current.GetInstance<FriendDataProvider>();
I get an ActivationException from the "Func..." declaration in the constructor of FriendDataProvider.
Can MEF do this at all? If yes, what attribute declarations are required?
[Export]
public class FriendDataProvider
{
private readonly Func<IDataService> _dataServiceCreator;
[ImportingConstructor]
public FriendDataProvider(Func<IDataService> dataServiceCreator) // <= DI ERROR
{
_dataServiceCreator = dataServiceCreator;
}
public void DoSomething()
{
using (var service = _dataServiceCreator()) // Factory
{ }
}
}
[Export(typeof(IDataService))]
public class DataService : IDataService
{
public ClassA GetSomething()
{
return new ClassA();
}
public void Dispose()
{ }
}
public interface IDataService : IDisposable
{
ClassA GetSomething();
}
public class ClassA
{ }
Most likely you are looking for MEF ExportFactory class:
https://msdn.microsoft.com/en-us/library/ff382807(v=vs.110).aspx
It'a a mixture of Owned<> and Func<> ideas from AutoFac. Mind that ExportFactory.CreateExport returns ExportLifetimeContext which is Disposable. Disposing the export lifetime context will also dispose the injected part + all its dependencies. ExportFactory behavior is slightly different depending on Instancing mode of the owner part. If the owner class is a singleton ExportFactory will always create you new instance (behaves like Func< Owned< T>> in Autofac), but if you use it in combination with CompositionScopes you'll get behavior similar to Func< T> in AutoFac. See example: http://blogs.microsoft.co.il/bnaya/2013/01/16/mef-20-mini-series-part-6-composition-scoping-and-lifetime-management/
Here is your example re-written using ExportFactories:
[Export]
public class FriendDataProvider
{
private readonly ExportFactory<IDataService> _dataServiceCreator;
[ImportingConstructor]
public FriendDataProvider(ExportFactory<IDataService> dataServiceCreator) // <= DI ERROR
{
_dataServiceCreator = dataServiceCreator;
}
public void DoSomething()
{
using (var service = _dataServiceCreator.CreateExport()) // Factory
{
}
}
}
[Export(typeof(IDataService))]
public class DataService : IDataService
{
public ClassA GetSomething()
{
return new ClassA();
}
public void Dispose()
{ }
}
public interface IDataService : IDisposable
{
ClassA GetSomething();
}
public class ClassA
{ }

CastleWindsor, Generic Repository and two database contexts

I have two separate databases for storing documents and users. Also I've implemented generic repository pattern:
public class Repository<T> : IRepository<T> where T : class
{
public DbContext Context { get; set; }
public Repository()
{
}
public IEnumerable<T> Get(Expression<Func<T, bool>> expression)
{
return Context.Set<T>().Where(expression).AsEnumerable();
}
public void Add(T entity)
{
Context.Set<T>().Add(entity);
}
public void Delete(T entity)
{
Context.Set<T>().Remove(entity);
}
public void Update(T entity)
{
Context.Set<T>().Attach(entity);
Context.Entry<T>(entity).State = EntityState.Modified;
}
public void SaveChanges()
{
Context.SaveChanges();
}
}
The problem is that entities are stored in different DbContexts and I can't use something like this:
container.Register(Component.For(typeof(IRepository<>)).ImplementedBy(typeof(Repository<>));
How can I specify which DbContext should be used for each entity?
For example, if I want create Repository that means that one database should be used, but if I want Repository another context should be used.
Or I should create two repo classes, like this:
public class AttachmetRepository<T> : IRepository<T> where T : class
{
public AttachmetsDbContext Context { get; set; }
...
}
public class UserRepository<T> : IRepository<T> where T : class
{
public UsersDbContext Context { get; set; }
...
}
The reason why I don't want to use two different repositories is to keep services simple, something like this:
public class SomeService: ISomeService
{
public IRepository<User> UserRepository { get; set; } //database 1
public IRepository<Comment> CommentsRepository { get; set; } //database 1
public IRepository<Attachment> AttachmentRepository { get; set; } //database 2
...
}
UPD:
As Ognyan suggested I've used FactoryMethod and this helped! Thanks a lot, Ognyan!
I'm new to CastleWindsor and I'm not sure its the best and fastest way, but here is my code:
public class EFDatabaseInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<AttContext>().LifeStyle.PerWebRequest);
container.Register(Component.For<DefContext>().LifeStyle.PerWebRequest);
container.Register(Component.For(typeof(IRepository<>)).UsingFactoryMethod((kernel, context) =>
{
var genericType = context.RequestedType.GetGenericArguments()[0];
Type type = typeof(Repository<>).MakeGenericType(genericType);
object repository = Activator.CreateInstance(type);
PropertyInfo dbContextProperty = type.GetProperty("Context");
if (genericType == typeof(Attachment))
{
dbContextProperty.SetValue(repository, kernel.Resolve<AttContext>());
}
else
{
dbContextProperty.SetValue(repository, kernel.Resolve<DefContext>());
}
return repository;
}).LifeStyle.PerWebRequest);
}
}
First you need not to hard code the DbContext inside the repository. You can remake your repository like this :
public class Repository<T> : IRepository<T> where T : class
{
private readonly DbContext _dbContext;
// you can even make it IDbContextProvider with .Current() method in order not
// to place a hard dependency but depend on Interface which is the proper way.
// I was in a hurry and did not want to overcomplicate the implementation.
public Repository(DbContext dbContext)
{
_dbContext = dbContext;
}
protected IDbSet<T> CreateSet<T>() where T : class
{
return _dbContext.Set<T>();
}
public virtual T Find(int id)
{
return CreateSet<T>().Find(id);
}
...
}
After that you need a factory method and a way to distinguish the destination db. One way to distinguish is to get the info from the CreationContext of the factory method :
private static DbContext DbContextFactoryMethod(IKernel k, ComponentModel cm, CreationContext c)
Here you can traverse the resolution stack and see if this is part of graph that contains IRepository or other entity and choose your database.
This way you will get the proper DbContext inside your repository without sticking all of them inside which will become more and more cumbersome with time.

Ninject Singleton Factory

I have a interface that is binded to a class. Everything work like excepted. I want to create the class with a constructor injection without passing my kernel everywhere. I want to have a singleton factory for these propose. How can i create one without using the ninject.extensions.factory library.
If you want to create a factory but without using the Factory Extension (not sure why, it's exactly what you need here I think) you can do something like the following:
public class FooFactory : IFooFactory
{
// allows us to Get things from the kernel, but not add new bindings etc.
private readonly IResolutionRoot resolutionRoot;
public FooFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IFoo CreateFoo()
{
return this.resolutionRoot.Get<IFoo>();
}
// or if you want to specify a value at runtime...
public IFoo CreateFoo(string myArg)
{
return this.resolutionRoot.Get<IFoo>(new ConstructorArgument("myArg", myArg));
}
}
public class Foo : IFoo { ... }
public class NeedsFooAtRuntime
{
public NeedsFooAtRuntime(IFooFactory factory)
{
this.foo = factory.CreateFoo("test");
}
}
Bind<IFooFactory>().To<FooFactory>();
Bind<IFoo>().To<Foo>();
The Factory Extension just does all of that work for you at runtime though. You only need to define the factory interface and the extension creates the implementation dynamically.
Try this code:
class NinjectKernelSingleton
{
private static YourKernel _kernel;
public static YourKernel Kernel
{
get { return _kernel ?? (_kernel = new YourKernel()); }
}
}
public class YourKernel
{
private IKernel _kernel;
public YourKernel()
{
_kernel = InitKernel();
}
private IKernel InitKernel()
{
//Ninject init logic goes here
}
public T Resolve<T>()
{
return _kernel.Get<T>();
}
}

Categories