I have a class, RepositoryManager, and I am using this class in some of my controllers:
public RepositoryManager
{
public IGenericRepository Repository {get; set;}
public RepositoryManager()
{
Repository = new GenericRepository(new MyEntities());
}
//...
}
I want to move IGenericRepository to a StructureMap Inversion of control (IoC) container
x.For<IGenericRepository>().Use<GenericRepository>().Ctor<MyEntities>("MyEntities");
Then I change my class constructor to that:
public RepositoryManager(IGenericRepository repository)
{
Repository = repository;
}
But the injection didn't work. I also tried to use the [SetterProperty] attribute on Repository, but still Repository didn't instantiate.
What did I do wrong?
My complete IoC initialization:
public static class IoC {
public static IContainer Initialize() {
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
});
x.For<IRepositoryManager>().Use<RepositoryManager>();
x.For<IGenericRepository>().Use<GenericRepository>().Ctor<MyEntities>("MyEntities");
});
return ObjectFactory.Container;
}
}
Basically your IoC initialisation is wrong for IGenericRepository. Change it to:
x.For<IGenericRepository>().Use(() => new GenericRepository(new MyEntities()));
In such a case, the constructor with parameter MyEntities will be called and an instance of MyEntities will be created and passed to that constructor as a parameter.
You do not need to register the concrete types; they will just be resolved by StructureMap. The scanner is already used with default conventions, so for the above example the following registration code is fully sufficient:
ObjectFactory.Initialize(x => x.Scan(scanner =>
{
scanner.TheCallingAssembly();
scanner.WithDefaultConventions();
}));
Related
I am trying to implement DI with Castle Windsor. Currently I have a controller with overloaded constructors like this (this is an antipattern as described here: https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=97):
public class MyController : ApiController
{
protected IStorageService StorageService;
protected MyController()
{
StorageService = StorageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity);
}
protected MyController(IStorageService storageService)
{
StorageService = storageService;
}
}
I am trying to get rid of the first constructor and have Castle Windsor handle the resolution of the storage service dependency.
I created a Castle Windsor installer class like this:
public class StorageServiceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IStorageService>()
.UsingFactoryMethod(
() => StorageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity)));
}
}
The problem is that User (which has type IPrincipal) is a property on ApiController, so it's not accessible from the installer. How can I make this work?
Update:
#PatrickQuirk seems to be implying that there is a better way to do this using Castle Windsor without needing a factory at all.
My StorageServiceFactory looks like this:
public static class StorageServiceFactory
{
public static IStorageService CreateStorageService(ClaimsIdentity identity)
{
if (identity == null)
{
return null;
}
Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier);
if (providerKeyClaim == null || string.IsNullOrEmpty(providerKeyClaim.Value))
{
return null;
}
StorageProviderType storageProviderType;
string storageProviderString = identity.FindFirstValue("storage_provider");
if (string.IsNullOrWhiteSpace(storageProviderString) || !Enum.TryParse(storageProviderString, out storageProviderType))
{
return null;
}
string accessToken = identity.FindFirstValue("access_token");
if (string.IsNullOrWhiteSpace(accessToken))
{
return null;
}
switch (storageProviderType)
{
// Return IStorageService implementation based on the type...
}
}
}
Is there a way to incorporate selecting the correct IStorageService into Windsor's dependency resolution and avoid the factory altogether? Or do I still need it?
I like #PatrickQuirk's solution, except that it seems odd to have to create a wrapper and corresponding wrapper interface for the factory just for the sake of dependency injection. Ideally I'd have the api controller's constructor take in an IStorageService as a parameter, which seems more intuitive/consistent with the field that actually needs to be set.
I don't think the multiple constructors is as much of a sin as the hidden dependency on StorageServiceFactory is, but I agree with your approach for the most part.
Instead of a factory method, pass a factory object into the class and have it create the storage service:
public class MyController : ApiController
{
protected IStorageService StorageService;
protected MyController(IStorageServiceFactory storageServiceFactory)
{
StorageService = storageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity);
}
}
And then define your factory interface and implementation:
public interface IStorageServiceFactory
{
IStorageService Create(ClaimsIdentity claimsIdentity);
}
public class StorageServiceFactoryImpl : IStorageServiceFactory
{
public IStorageService Create(ClaimsIdentity claimsIdentity)
{
return StorageServiceFactory.CreateStorageService(claimsIdentity);
}
}
This way, you have a single constructor and the dependency on the storage service factory is explicit.
Regarding your update:
...it seems odd to have to create a wrapper and corresponding wrapper interface for the factory just for the sake of dependency injection.
Well, that's kind of the point of dependency injection.
The wrapper I propose is solving two problems: it removes the need to call a static method from inside your class (hiding a dependency), and allows for delayed resolution (because your dependency relies on member data to be created).
If you have a way to change the dependencies of creating an IStorageService to not rely on a member of the class you're giving it to, then you could pass one in directly (provided you can tell Windsor how to create one).
I'm trying to get the following scenario using autofac but I'm not sure how my code will be built to get this up & running.
I have a repository class, this repository class needs to get a project key (string) on initialization (constructor). I want to instantiate this repository in initialization of my "Initialize" method provided to my by Web Api, because the project key will be available in my route.
so instead of calling "new ProductRepository(projectKey)", I want to use Autofac. Can someone point me in the right direction? I didn't find any way to send in specific data to the container in web api, since the container/builder is only available in the appStart.
Should I make the container available as a singleton so that I can approach it, or is this bad practice?
in your initialization code:
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = resolver;
in your controller:
public class MyController : ApiController
{
public MyController(IComponentContext container)
{
var key = new NamedParameter("projectKey", "keyFromRoute");
var repository = container.Resolve<ProductRepository>(key);
}
}
That should do it.
There is a nuget package that provides a DependencyResolver for WebApi that integrates with AutoFac. Create the DependencyResolver, assign it to the config, register your controllers in the autofac container.
I'm making some assumptions because you didn't provide your code, but I think you have something like this:
public class ProductRepository
{
public ProductRepository(DbContext dbContext, int projectKey)
{
}
}
public class SomeController : Controller
{
private readonly Func<int, ProductRepository> _repoFactory;
public SomeController(Func<int, ProductRepository> repoFactory)
{
_repoFactory = repoFactory;
}
public void DoStuff(int projectKey)
{
var repo = _repoFactory(projectKey);
repo.DoStuff();
}
}
public class RepositoryModule : Module
{
public override Load(ContainerBuilder builder)
{
builder.RegisterType<ProductRepository>();
}
}
I am trying to understand the delegate factory pattern with Autofac. I know how to implement factory using IIndex<> with Keyed() registration, which is explained nicely in here: Configuring an Autofac delegate factory that's defined on an abstract class
I would like to know if I can create a factory using Func<>, and how would I do the registrations for the following sample:
public enum Service
{
Foo,
Bar
}
public interface FooService : IService
{
ServiceMethod();
}
public interface BarService : IService
{
ServiceMethod();
}
public class FooBarClient
{
private readonly IService service;
public FooBarClient(Func<Service, IService> service)
{
this.service = service(Service.Foo);
}
public void Process()
{
service.ServiceMethod(); // call the foo service.
}
}
Autofac cannot construct this Func<Service, IService> for you which lets you return different types based on a parameter. This is what IIndex<> is for.
However if you don't want/cannot use IIndex<> you can create this factory function with the help of the Keyed or Named and register your factory in the container:
var builder = new ContainerBuilder();
builder.RegisterType<FooBarClient>().AsSelf();
builder.RegisterType<FooService>().Keyed<IService>(Service.Foo);
builder.RegisterType<BarService>().Keyed<IService>(Service.Bar);
builder.Register<Func<Service, IService>>(c =>
{
var context = c.Resolve<IComponentContext>();
return s => context.ResolveKeyed<IService>(s);
});
I'm trying to setup a base Repository class that can use the Entity Framework edmx model context. The problem I'm having is that I need to find an interface that the EF EDMX object context implements so I can pass to the constructor via dependency injections. I've got around this before by using a DataFactory that creates it and stores it in the HttpContext but that kills the ability to unit test. Any help would be appreciated. Thanks!
public abstract class BaseRepository<T> where T : EntityObject
{
private MyDataModelContext _dataContext;
private ObjectSet<T> dbset;
protected BaseRepository(IObjectContext dataContext)
{
_dataContext = dataContext;
dbset = _dataContext.CreateObjectSet<T>();
}
.....
I've always created a DataContextFactory that passes my own interface to the Context, and passed that to my repositories like so:
The context interface:
public IMyDataContext {
// One per table in the database
IDbSet<Class1> Class1s { get;set; }
// etc
// The standard methods from EF you'll use
void Add( object Entity );
void Attach( object Entity );
void Delete( object Entity );
void SaveChanges();
}
The context factory:
public class MyDataContextFactory : IMyDataContextFactory {
public IMyDataContext GetContext() {
// TODO: Use the service locator pattern to avoid the direct instanciation
return new MyDataContext();
}
}
The context factory interface:
public interface IMyDataContextFactory {
IMyDataContext GetContext();
}
The repository:
public class MyClass1Repository {
private readonly IMyDataContextFactory factory;
public MyClass1Repository( IMyDataContextFactory Factory ) {
// TODO: check for null
this.factory = Factory;
}
public List<MyClass1> GetAll() {
using ( IMyDataContext db = this.factory.GetContext() ) {
return db.Class1s.ToList();
}
}
// TODO: Other methods that get stuff
}
Then when I want to test the repository, I pass in a fake IMyDataContextFactory that returns a fake IMyDataContext from GetContext().
In time I notice duplication in repositories, and can push certain methods into the base repository: GetAll(), Save(), GetById() sometimes if I have consistent primary keys, etc.
I installed on my project Ninject.MVC3 via Nuget.
I read this article that to inject dependencies in my controllers, all you had to do was install Ninject, add my dependencies in NinjectMVC3.cs and ready.
So far so good, but how to retrieve the instance of an object?
public ActionResult MyAction()
{
var myObject = /* HERE ??*/
}
In the constructor of the controller I have no problems!
public class AccountController : Controller
{
public AccountController(IRepository repository) { ... } //This works!!
}
The reason it works is because the ControllerFactory looks for DI and automatically adds it. If you want to get a specific instance you can do this:
private static void RegisterServices(IKernel kernel) {
kernel.Bind<ICoolObject>().To(CoolObject);
}
public ActionResult MyAction() {
var myObject =
System.Web.Mvc.DependencyResolver.Current.GetService(typeof (ICoolObject));
}
Becareful though. This is done quite often with those new to Dependency Injection (myself included). The question is why do you need to do it this way?