Autofac. Base Class properties resolved without specific injection - c#

I'm looking for a possible solution to the following.
I have a base class that has a dependency which I currently use property injection to satisfy.
public class BaseClass {
IService SomeService { get; set; }
}
I have multiple classes which inherit from this base class.
public class DerivedClass : BaseClass, IDerivedClass {
}
And I inject using the following.
builder.RegisterType<DerivedClass>().As<IDerivedClass>().OnActivated(e => e.Instance.SomeService = e.Context.Resolve<IService>());
I do this for about 12 other classes which extend the base class. Is there a way so that any class extending BaseClass will get my IService registration without setting up an Activation event for each registration? It's working fine like this, but would just like to clean up the registrations.

Just use constructor injection. Create constructor with parameters for your class like
public DerivedClass(IServiceOne service1, IService2 service2)
{
this._service1 = service1;
this._service2 = service2;
}
and make autofac doing his job automatically, like
builder.RegisterType<T>();

Related

c# class inherits from base class with constructor with dependency injection

I have a project using Dependency Injection (Ninject) where I have the following class:
public class SecurityService : BaseService
{
ISecurityRepository _securityRepo = null;
public SecurityService(ISecurityRepository securityRepo)
{
_securityRepo = securityRepo;
}
}
Because BaseService is going to be referenced in many other service classes I wanted to add there a method that also go to Data Repository and get some information so I don't have to repeat the same code along the other service classes.
Here is what I have for BaseRepository:
public partial class BaseService
{
IEntityRepository _entityRepo = null;
public BaseService(IEntityRepository entityRepo)
{
_entityRepo = entityRepo;
}
public Settings AppSettings
{
get
{
return _entityRepo.GetEntitySettings();
}
}
}
But when I compile I get the following error:
There is no argument given that corresponds to the required formal parameter 'entityRepo' of 'BaseService.BaseService(IEntityRepository)'
And the error make sense because now I have a constructor that I guess is expecting something.
Any clue how to fix this but that I can still have my dependency injection in BaseRepository class?
UPDATE
I just tried to remove the constructor and use the attribute [Inject] but when debugging I see that _entityRepo is NULL.
Add the dependency to the constructor for the derived class, and pass it along.
public SecurityService(ISecurityRepository securityRepo, IEntityRepository entityRepo)
: base(entityRepo)
{
_securityRepo = securityRepo;
}
I could make it work:
I just convert the private property to be public and then [Inject] attribute started to work.
public partial class BaseService
{
[Inject]
public IEntityRepository EntityRepo { get; set; }
}
Pass the Repository object to the base class via the child class constructor:
public SecurityService(ISecurityRepository securityRepo) : base(IEntityRepository)
{
//Initialize stuff for the child class
}

Resolve dependencies from inherited classes with Autofac

First of all, let me provide some sample code:
public abstract class BaseEntity { }
public class MyEntity : BaseEntity { }
public class MyCustomEntity : BaseEntity { }
public interface IStore<TEntity> where TEntity : BaseEntity { }
public class BaseStore<TEntity> : IStore<TEntity> where TEntity : BaseEntity { }
public class MyCustomEntityStore : BaseStore<MyEntity> { }
So basically I have an abstract entity and two derived types. I created a repository class which is hiding all the basic stuff around the BaseEntity (for example fill the "LastModifiedBy" property). But for some cases, I need specific behaviour to saving an entity, so I need to derive from the BaseStore, and implement the custom behaviour in MyCustomEntityStore. So far, it is easy.
The problem is i would like to use Autofac to resolve dependencies in my application. My goal would be to do this:
public class SomeClass {
private readonly IStore<MyEntity> MyEntityStore;
private readonly IStore<MyCustomEntity> MyCustomEntityStore;
public SomeClass(IStore<MyEntity> mes, IStore<MyCustomEntity> mces)
{
MyEntityStore = mes;
MyCustomEntityStore = mces;
}
}
I would like to inject an instance of BaseStore<MyEntity> to IStore<MyEntity> and MyCustomEntityStore to IStore<MyCustomEntity>. This is working fine with the MyCustomEntityStore (which has a concrete implementation derived from the base store), but i do not want to create empty classes just to inherit the BaseStore<MyEntity>. I registered my components like this:
builder.RegisterAssemblyTypes(Assembly.Load("Project.Data")).Where(t => t.Name.EndsWith("Store")).AsImplementedInterfaces().InstancePerRequest();
Although these instances can be in the place of these interfaces, Autofac can not resolve the IStore<MyEntity>.
Thanks for all the help!
I managed to solve the problem with this registering:
builder.RegisterGeneric(typeof(BaseStore<>))
.As(typeof(IStore<>))
.InstancePerRequest();
builder.RegisterAssemblyTypes(Assembly.Load("Project.Data"))
.Where(t => t.Name.EndsWith("Store"))
.AsImplementedInterfaces()
.InstancePerRequest();
Can anyone confirm, this is the right way?

Nested Generics and Dependency Injection C#

I'm relatively new to dependency injection. I think I get the idea, but I'm now presented with this problem. Assume that I have some interfaces and some classes:
interface IA<T>
interface IB<IA<T>>
class A<T> : IA<T>
class B<IA<T>> : IB<IA<T>>
I want to register the following in my dependency injection container:
container.Register<IB<IA<T>>, B<A<T>>(...);
When I try to resolve IB<IA<T>>, it fails with an exception explaining that IB<IA<T>> cannot be converted to B<A<T>>.
Why did it fail, and how can I fix it?
Like Alexei posted already you wouldn't use generics that way. You would probably want something like this instead:
public interface IA<T>
{
T Item { get; }
}
public interface IB<T>
{
IA<T> IA { get; }
}
Sample implementations:
public class A<T> : IA<T>
{
public T Item
{
get;
set;
}
}
public class B<T> : IB<T>
{
public B(IA<T> ia)
{
this.IA = ia;
}
public IA<T> IA
{
get;
private set;
}
}
Since the subject is dependency injection notice the B implementation does not have parameterless constructor. Instead it notifies its dependency in the constructor.
Setting up the container, first register IA implementation:
container.Register<IA<int>, A<int>>(); // specific implementation or
container.Register(typeof(IA<>), typeof(A<>)); // generic registration
Registering IB would be the same and the container should take care of injecting the dependency to class B's constructor:
container.Register<IB<int>, B<int>>();
container.Register(typeof(IB<>), typeof(B<>));
Resolving at runtime you would need to specify the type:
var intIB = container.Resolve<IB<int>>();
var stringIB = container.Resolve<IB<string>>();

Why set up a constructor in a class to set a base parameter when I could do the same in a class it inherits from?

I have the following code:
public abstract class ApiBaseController : ApiController
{
protected IUow Uow { get; set; }
}
and:
public class ContentStatusController : ApiBaseController
{
public ContentStatusController(IUow uow)
{
Uow = uow;
}
}
Is there any reason why I could not code the assignment of Uow (using IOC) in the ApiBaseController?
The reason I ask is because I am trying to do something similar to the Code Camper application sample and I notice that in that sample the Unit of work is assignment is always performed in the constuctors of the controllers themselves rather than in the ApiBaseConstructor. In the examples I see this is the only thing that's done in the constructors.
If I did the assignement in the base controller then how could I code that and would Uow still need to have "protected" for it to be available in controllers that inherit from the ApiBaseController?
Your IOC container is injecting dependencies via constructors. If you want to continue to use that mechanism (some containers allow e.g. property injection, but not everyone likes to do that) then you'll still need to have the same constructor in your derived class to pass the injected component down to the base class1.
Something like:
public abstract class ApiBaseController : ApiController
{
public ApiBaseController(IUow uow)
{
Uow = uow;
}
protected IUow Uow { get; private set; }
}
public class ContentStatusController : ApiBaseController
{
public ContentStatusController(IUow uow) : base(uow) //<-- This is needed
{
}
}
1Because classes don't inherit constructors.

Missing constructor in a class derrived from a generic class

I'm trying to create a generic LINQ-TO-SQL repository based on this post which basically lets you define a generic base repository class, then you can define all of your actual repository classes by deriving from the generic base.
I want the option of using a repository with or without passing in the data context, so I decided to create two constructors in the generic base class:
public abstract class GenericRepository<T, C>
where T : class
where C : System.Data.Linq.DataContext, new()
{
public C _db;
public GenericRepository()
{
_db = new C();
}
public GenericRepository(C db)
{
_db = db;
}
public IQueryable<T> FindAll()
... and other repository functions
}
To use it, I would derrive my actual repository class:
public class TeamRepository : GenericRepository<Team, AppDataContext> { }
Now, if I try to use this with a parameter:
AppDataContext db = new AppDataContext();
TeamRepository repos=new TeamRepository(db);
I get the error:
'App.Models.TeamRepository' does not contain a constructor that takes 1 arguments
So, it looks like you cant inherit constructors in C#, so, how would you code this so I can call: TeamRepository() or TeamRepository(db)
Derived classes do not automatically inherit any base class's constructors, you need to explicitly define them.
public class TeamRepository : GenericRepository<Team, AppDataContext>
{
public TeamRepository() : base() { }
public TeamRepository(AppDataContext db) : base(db) { }
}
Do note however that if the base class defines (implicitly or explicitly) an accessible default constructor, constructors of the derived class will implicitly invoke it unless the constructor is invoked explicitly.
You're correct, constructors in C# are not bubbled up into subclasses. You'll have to declare them yourself. In your example, you'll need to surface two constructors for each of your repositories.

Categories

Resources