I Have An IDbContext Interface In Another Assembly And A Service Stack In Another Assembly , The Base Service Class has a Property Of IDbContext and other Services Do Use Its Property.
To Make Matters Simple I Omit The Base Service Class And even in this Scenario it does not work.
here is IDbContext :
public interface IDbContext
{
}
Then I Have a DBContext Class Which Implements IDbContext.
In Another Assembly We Have This Class Which has A IDContext Property :
public class StudyFieldService : IStudyFieldService{
private readonly IDbSet<StudyField> _studyFields;
public IDbContext DbContext { get; set; }
public StudyFieldService(IDbContext db)
{
_studyFields = DbContext.Set<StudyField>();
}
}
Then I have Autofac Registry Class Which Maps Classes To Interfaces and the Registry Class Is Also in Another Assembly
This Is The Body Of The Method Which maps the types :
var builder = new ContainerBuilder();
builder.RegisterType<SalaryDbContext>().As<IDbContext>().InstancePerLifetimeScope();
builder.RegisterType<StudyFieldService>().As<IStudyFieldService>().PropertiesAutowired();
Now if I Put The IDbContext In The Constructor Param Autofac Resolves it but I Want it to be injected as a property and Automatically.
I reckon you should remove the constructor injection and change the DbContext variable name to something else or use this.DbContext to make it work.
public class StudyFieldService : IStudyFieldService{
private readonly IDbSet<StudyField> _studyFields;
public IDbContext Context{ get; set; }
public StudyFieldService()
{
_studyFields = Context.Set<StudyField>();
}
}
I guess there is a conflict on variable name with ef DbContext
Related
Currently I have a simple generic abstract class with one service parameter in constructor which is resolved by dependency injection.
public abstract class CosmosCommandHandler<T>
{
protected readonly ICosmosStore<T> _cosmosStore;
protected CosmosCommandHandler(ICosmosStore<T> cosmosStore)
{
_cosmosStore = cosmosStore;
}
}
and some concrete class inheriting from it
public class FooCommandHandler : CosmosCommandHandler<Foo>
{
private readonly IFooService _fooService;
public FooCommandHandler(ICosmosStore<Foo> cosmosStore, IFooService fooService)
: base(cosmosStore)
{
_fooService = fooService;
}
}
This is all fine, but I want to add a new service to abstract class and resolve it with DI as well. My idea is that I should use constructor chaining for this, but it's not working out.
Something like this.
public abstract class CosmosCommandHandler<T>
{
private readonly IAuditService _auditService;
protected readonly ICosmosStore<T> _cosmosStore;
private CosmosCommandHandler(ICosmosStore<T> cosmosStore, IAuditService auditService)
{
_cosmosStore = cosmosStore;
_auditService = auditService;
}
protected CosmosCommandHandler(ICosmosStore<T> cosmosStore)
: this(cosmosStore, IAuditService auditService)
{
}
}
Obviously I could just pass the IAuditService from FooCommandHandler just like ICosmosStore, but that doesn't seem right as FooCommandHandler has nothing to do with IAuditService. It is out of its scope.
Is this possible to achieve?
If IAuditService is out of the FooCommandHandler scope, then create child of your CosmosCommandHandler class which will have that IAuditService. And that child also could be abstract class.
Also, you could create additional overloaded constructor for your CosmosCommandHandler class - and that FooCommandHandler class does not need to use it. But that also breaks the concept of inheritance because FooCommandHandler class has nothing to do with IAuditService.
I have a generic UnitOfWork pattern implementation and these UnitOfWork objects are dependencies to my service classes. Below snippets should help the reader understand my code setup:
IUnitOfWork interface
public interface IUnitOfWork<out TContext> where TContext : IDbContext
UnitOfWork class
public sealed class UnitOfWork<TContext> : IDisposable, IUnitOfWork<IDbContext> where TContext : IDbContext
{
private static readonly ILog Log = LogManager.GetLogger(typeof(UnitOfWork<TContext>));
private readonly IDbContext _dbContext;
private Dictionary<string, IRepository> _repositories;
private IDbTransaction Transaction { get; set; }
public UnitOfWork(IDbContext context)
{
_dbContext = context;
}
}
Container registrations:
builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>));
builder.RegisterType<ReconciliationDbContext>().As<IDbContext>();
builder.RegisterType<GenevaDataDbContext>().As<IDbContext>();
builder.RegisterType<OpenStaarsDbContext>().As<IDbContext>();
builder.RegisterType<UnitOfWork<ReconciliationDbContext>>().Keyed<IUnitOfWork<IDbContext>>(ContextKey.Recon);
builder.RegisterType<UnitOfWork<OpenStaarsDbContext>>().Keyed<IUnitOfWork<IDbContext>>(ContextKey.OpenStaars);
builder.RegisterType<CommentsService>().As<ICommentsService>().WithAttributeFiltering();
DbContext classes:
public class ReconciliationDbContext : BaseDbContext<ReconciliationDbContext>, IDbContext
{
private const string DbSchema = "BoxedPosition";
public ReconciliationDbContext() : base("Reconciliation")
{
}
}
public class OpenStaarsDbContext : BaseDbContext<OpenStaarsDbContext>, IDbContext
{
public OpenStaarsDbContext() : base("OpenStaars")
{
}
}
CommentsService class:
public class CommentsService : ICommentsService
{
private readonly IUnitOfWork<IDbContext> _reconciliationUoW;
public CommentsService([KeyFilter(ContextKey.Recon)] IUnitOfWork<IDbContext> reconciliationUoW)
{
_reconciliationUoW = reconciliationUoW;
}
}
Resolving ICommentsService:
var commentsService = container.Resolve<ICommentsService>();
Now when I try to resolve the ICommentsService type, it instantiates the UnitOfWork dependency. However, the UnitOfWork._dbContext property evaluates to OpenStaarsDbContext type. This is particularly strange considering our registrations.
It becomes more strange if we re-order our IDbContext registrations by registering the GenevaDataDbContext after OpenStaarsDbContext. Now the _dbContext evaluates to GenevaDataDbContext instance.
How can I fix this to make the reconciliationUoW dependency of CommentsService to have the correct instance of ReconciliationDbContext ?
The reason of such behaviour is the fact you inject IDbContext into your UnitOfWork constructor, instead of TContext - the container just ignores the type you provide as a generic parameter in you registration and takes the first IDbContext it finds in the container - which would be the last registered, no matter what key you would use.
To make it work, instead of using keyed registration, you could simply inject IUnitOfWork<ContextYouNeed> instead of IUnitOfWork<IDbContext> - it would simplify the code as well. First you need to fix your UnitOfWork class:
class UnitOfWork<TContext> : IUnitOfWork<TContext> where TContext : IDbContext
{
private readonly TContext _context;
public UnitOfWork(TContext context)
{
_context = context;
}
}
In your registration, you do not need to register specific unit of work types, standard generic registration would be sufficient. But you need to register your context types AsSelf as well, so Autofac would properly inject it for your unit of work instances:
builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>));
builder.RegisterType<ReconciliationContext>().As<IContext>().AsSelf();
builder.RegisterType<OpenStaarsContext>().As<IContext>().AsSelf();
Later on, in your service simply inject proper unit of work:
public CommentsService(IUnitOfWork<ReconciliationContext> reconciliationUoW)
Lets say i have the following setup
public interface IDocuments {}
public interface IPeople {}
public class Documents : IDocuments
{
public Documents(IRepository repo){ ... };
}
public class People : IPeople
{
public People(IRepository repo) { ... }
}
public class Controller1
{
public Controller1(IDocuments documents){}
}
public class Controller2
{
public Controller2(IDocuments documents, IPeople people){}
}
How can I setup StructureMap to inject a different transient instance of IRepository into the dependency chain for Controller1 and for Controller2.
So to clarify:
There should be 2 instances of IRepository.
The first instance will be injected into the documents instance for controller1.
The second instance will be injected into Documents and People instances for controller2.
several classes in my dll require a set of the data ( general configurations ) . these data are provided by the one who uses the dll through implementing an interface IConfigs . so data should be injected as a dependency . now I wonder how to do that .
Update :
sorry , if the question was not clear . the problem is should I have an instance of IConfigs in each class that needs it and using constructor injection ( that I don't like this approach ) or there is a cleaner way to handle this situation ?
You can use injection dependency by property.
If you use MEF :
Service
[Export(typeof(IServiec))]
public class Service : IService
{
....
}
Client
public class Client
{
[Import]
public IService Service
{
}
}
Nota : You add lines in order to register your catalog and container
If I understand you correctly, you want do register different derived classes with one interface, don't know what IoC Container you uses, but in here I uses Unity as in sample code, but most of other IoC Containers support using one string to differentiate registration in one interface. Assume you have:
public interface IConfig {}
public class ConfigA : IConfig {}
public class ConfigB : IConfig {}
So you can register both ConfigA and ConfigB to IConfig with different name:
var container = new UnityContainer();
container.RegisterType<IConfig, ConfigA>("A");
container.RegisterType<IConfig, ConfigA>("B");
public class MainClass
{
private IConfig _config;
public MainClass([Dependency("A")] IConfig config)
{
_config = config;
}
}
If you don't want to use constructor dependency, use property:
public class MainA
{
[Dependency("A")]
private IConfig Config { get; set; }
}
As your helper classes are static, you won't be able to use DI unless you use a ServiceLocator style and have your helper class retrieve injected values itself, something like this:
public static class HelperClass
{
static HelperClass()
{
var config = ServiceLocator.Get<IConfig>();
UserId = config.Get("UserId");
}
public static int UserId { get; private set; }
}
This is not considered good practice because your helper class then has a hidden dependency on your ServiceLocator being set up with an IConfig which contains a UserId.
I'd therefore recommend you change your helper class to be non-static, and have the IConfig it needs injected into it via its constructor, like this:
public class HelperClass
{
public HelperClass(IConfig config)
{
UserId = config.Get("UserId");
}
public int UserId { get; private set; }
}
You can then inject your HelperClass into your service classes via their constructors, like this:
public class ServiceClass
{
private readonly HelperClass _helperClass;
public ServiceClass(HelperClass helperClass)
{
_helperClass = helperClass;
}
}
This way each component can be swapped out, stubbed or mocked as necessary. If your HelperClass has no state of its own you can configure your DI container to manage it with a Singleton lifetime, which essentially makes it 'static' with none of the disadvantages.
Currently when I need to inject dependencies into base class, I use the following code:
public class BaseClass
{
readonly IService _service;
public BaseClass(IService service)
{
_service = service;
}
}
public class A : BaseClass
{
public A(IService service) : base(service)
{
}
}
public class B : BaseClass
{
public B(IService service) : base(service)
{
}
}
I have to write a lot of duplicate code in all sub classes. To avoid these duplicate code, I think I can use CommonServiceLocator to inject dependencies into the base class:
public class BaseClass
{
readonly IService _service;
public BaseClass()
{
_service = ServiceLocator.Current.GetInstance<IService>();
}
}
public class A : BaseClass
{
}
public class B : BaseClass
{
}
This seems to be much simpler, but I'm not sure if this is a good practice.
Thanks
Requesting a dependency from within a class is called the Service Locator Pattern, which is an anti-pattern. Prevent to minimize the dependency between your application and the IoC framework, even if it is the Common Service Locator.
I would still go for the first approach, but I agree that if the base class always needs that dependency and you have many sub types, this can become cumbersome. In that case, go for property injection:
public class BaseClass
{
public BaseClass()
{
}
public IService Service { get; set; }
}
This way your library is free from using a Service Locator. One of the greatest advantages of this approach for me, is that it makes writing unit tests much less painful.