C# Dependency injection duplicating - c#

I'm making an ASP.NET Core Razor Pages web application. In my application I use the following code:
public class MyClass
{
private readonly ApplicationDbContext _dbContext;
private readonly ICalendarService _calendarService;
public MyClass(ApplicationDbContext dbContext, ICalendarService calendarService)
{
_dbContext = dbContext;
_calendarService = calendarService;
}
public void MyFunction()
{
// here I need to use _dbContext and _calendarService
}
But when I use this class I need to do the following:
public class MySecondClass
{
private ImportIntoCalendar ImportHintSchedule;
public MySecondClass()
{
MyClass= new MyClass(_dbContext, _calendarService);
}
// Do something with variable ImportHintSchedule
ImportHintschedule.Function()
}
Everytime I need to add the dbcontext and the calendarservice into the parameters. So both need to be available in the other class. This feels like I'm doing something stupid, like I'm duplicating the same step. Does anybody know a better way to do this. Or is this just fine?
Edit:
I have this line in my startup.cs
services.AddScoped<ICalendarService, CalendarService>();

In your ConfigureServices you can add the IOC scopes.
For example, something like this. I don't know all of your code so the is just an example.
services.AddScoped<ICalendarService, CalendarService>();
services.AddScoped<IApplicationDbContext, ApplicationDbContext>();
You can also add singletons if that meets your needs as well.
Here is an example singleton call I use in my application
services.AddSingleton<IRepository<BaseItem>>(x => new Repository<BaseItem>(Configuration["MongoConnection:DefaultConnection"]));

I would suggest to create an Interface of your class, something like:
public interface IMyClass {
void MyFunction();
}
Then, implement that in your class:
public class MyClass : IMyClass {
private readonly ApplicationDbContext _dbContext;
private readonly ICalendarService _calendarService;
public MyClass(ApplicationDbContext dbContext, ICalendarService calendarService)
{
_dbContext = dbContext;
_calendarService = calendarService;
}
public void MyFunction()
{
// here I need to use _dbContext and _calendarService
}
}
And the add that to injector:
public void ConfigureServices(IServiceCollection services)
{
// existing code
services.AddTransient<IMyClass, MyClass>();
}
and finally use IMyClass in Controller constructor.
public class MyController:Controller
{
private IMyInterface _myClass;
public MyController(IMyInterface myclass) {
_myClass = myClass;
}
public IActionResult MyAction() {
_myClass.MyFunction();
return View();
}
}

Related

How to mock the dependency injection object in unit test

My project requires unit testing. I am using constructor dependency injection in my controller. When I mock the injected dependency object in my unit testing project and call it in a test method. Returns null in all cases.
Controller Class:
public class Owner:Controller
{
private readonly IComRepository repository;
private readonly DbContext context;
public Owner(IComRepository repository, DbContext context)
{
this.repository=repository;
this.context=context;
}
[HttpGet("GetAllTypes")]
public async Task<IActionResult> GetAllTypes()
{
var ownerTypes=repository.GetTypes();
return Ok(ownerTypes);
}
}
My Repository Class
public Interface IComRepository
{
IList<Type> GetTypes();
}
public Class ComRepository : IComRepository
{
private readonly DbContext context;
public ComRepository(DbContext context)
{
this.context=context;
}
public IList<Type> GetTypes()
{
var allTypes= context.Types.ToList();
return allTypes;
}
}
Now I need to test the GetAllTypes methods in my controller class. My Test Class is below mentioned:
using moq;
[TestClass]
public Class OwnerTest
{
public OwnerTest()
{
var mockIcomrepo = new Mock<IComRepository>();
var mockDbcontext = new Mock<Dbcontext>();
OwnerController owner = new OwnerController(mockDbContext.Object, mockIcomrepo.Object);
}
[TestMethod]
public void GetTypes()
{
var allTypes= owner.GetAllTypes(); //It's not trigger to my controller
Assert.AreEqual(5,allTypes.count());
}
}
How can I do it? Any one know the answer for this question.
As #Nkosi mentioned you have to use moq setup. Define your mocks outside constructor and initalize them in test class's constructor.
using moq;
[TestClass]
public Class OwnerTest
{
private readonly IComRepository _mockRepository;
private readonly OwnerControler _ownerController;
//your mock data
private readonly IList<Type> mockData;
public OwnerTest()
{
_mockRepository= new Mock<IComRepository>();
_ownerController = new OwnerController(mockDbContext.Object, mockIcomrepo.Object);
mockData=new IList<Type>{"Data1","Data2","Data3","Data4","Data5"};
}
//choose better names for testing a method
//Naming convention like this MethodName_StateUnderTest_ExpectedResult;
[TestMethod]
public void GetAllTypes()
{
_mockRepository.Setup(p=>p.GetAllTypes()).Returns(mockData);
var result= _ownerController.GetAllTypes();
var okResult=Assert.IsType<OkObjectResult>(result)
var returnTypes=Assert.IsAssignableFrom<IList<Type>>(okResult.Value);
Assert.AreEqual(5,returnTypes.count());
}
}
Also, why you inject your dbcontext to controller?your repository should depend dbcontext not controller.

Dependency injection IOption class library

I have a class library where I want to access a Connectionstring from appsettings.json.
appsettings.json :
"DatabaseSettings": {
"ConnectionString": "Server=.;Database=Test;Trusted_Connection=True;"
},
In startup.cs I have the following code:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<DatabaseSettings>(Configuration.GetSection("DatabaseSettings"));
services.AddOptions();
services.AddTransient<IConnectionOption, Class1>();
}
And in class library
IConnectionOption.cs
public interface IConnectionOption
{
void ReadValue();
}
Class1.cs
public class Class1 : IConnectionOption
{
private readonly DatabaseSettings test;
public Class1(IOptions<DatabaseSettings> dbOptions)
{
test = dbOptions.Value;
}
public void ReadValue()
{
var r = test;
}
}
Now from index.cshtml I want to Invoke the class Library Class1
public class IndexModel : PageModel
{
public void OnGet()
{
Class1 test = new Class1();
test.ReadValue();
}
}
But of course that doesnt work since there are no Constructor taking zero parameters, I don´t think I should add IOptions as an parameter. But how do I invoke the class library to read the connectionstring? (When I get this to work I will of course read data and return instead of the connectionstring). I have looked at several examples including net core 2.1 Dependency injection
But I don´t understand how to use the class library directly, Is it necessary to use an controller ?!
If DatabaseSettings is accessible to the class library, there really is not much need for tightly coupling Class1 library to IOptions, which is more framework related.
Ideally Class1 can explicitly depend on DatabaseSettings via explicit constructor injection
public class Class1 : IConnectionOption {
private readonly DatabaseSettings test;
public Class1(DatabaseSettings settings) {
test = settings;
}
public void ReadValue() {
var r = test;
//...
}
}
then in Startup, the dependency can be extract from configuration and registered with the DI container
public void ConfigureServices(IServiceCollection services) {
var settings = Configuration.GetSection("DatabaseSettings").Get<DatabaseSettings>();
services.AddSingleton<DatabaseSettings>(settings);
services.AddTransient<IConnectionOption, Class1>();
}
That way when ever Class1 is resolved, the container will know how to inject the DatabaseSettings dependency.
Another option could have also been to use the factory delegate
public void ConfigureServices(IServiceCollection services) {
var settings = Configuration.GetSection("DatabaseSettings").Get<DatabaseSettings>();
services.AddTransient<IConnectionOption, Class1>(_ => new Class1(settings));
}
That way, when the IndexModel depends on IConnectionOption for injection.
public class IndexModel : PageModel {
private readonly IConnectionOption connectionOption;
public IndexModel(IConnectionOption iConnectionOption) {
connectionOption = iConnectionOption;
}
public void OnGet() {
connectionOption.ReadValue();
//...
}
}
the proper dependency will be injected when the page model is initialized.
You are using Dependency Injection but only halfway. This is what you are missing:
Register the service in the container (I'm going to assume a better name for Class1):
services.AddScoped<IConnectionOption, DatabaseConnectionOption>();
Make the page receive the service:
public class IndexModel : PageModel
{
private readonly IConnectionOption _IConnectionOption;
public IndexModel(IConnectionOption iConnectionOption)
{
_IConnectionOption = iConnectionOption;
}
public void OnGet()
{
_IConnectionOption.ReadValue();
}
}

.Net Core Dependency Injection Get different instance generated by Two Factory Methods

I have two static classes with single static factory method for each.
public static class First
{
public IMyService Factory()
{
return IMyService()
{
//configure with Configs
};
}
}
public static class Second
{
public IMyService Factory()
{
return IMyService()
{
// configure with different Configs
};
}
}
The following would make provider return an instance when asked for:
services.AddSingleton(mb =>
{
var myService= First.Factory();
return myService;
});
How do I call different factories when need to get an instance with different configs?
If it's a one-time decision (app startup) than you should extract your config as a dependency:
in appsettings.json:
"mysettings":{"bla":"val1"}
somewhere in project:
public class mysettings { public string bla {get;set; }
in myservice constructor:
public myservice(IOptions<mysettings> settings) { ... }
in startup.cs:
services.Configure<mysettings>(this.Configuration.GetSection("mysettings"));
services.AddSingleton<Imyservice, myservice>();
Like this you inject the settings and your service will be instantiated with those that are specified in the appsettings.json
If you need to deside "live" which settings to use:
public interface IMyServiceFactory{
IMyService Create(MySettings settings);
}
Than you inject IMyServiceFactory to the class where you want to use IMyService and instantate it there with the right settings. Or even:
public interface IMyServiceFactory{
IMyService Create1();
IMyService Create2();
}
In any case you just register the factory in startup:
services.AddSingleton<IMyServiceFactory, MyServiceFactory>();
Somehow your client code or the bootstrapping code needs to express what kind of implementation is needed. You could implement it the following way:
public Interface IReqeust
{
// Some code
}
public class HttpRequest : IRequest
{
// Implementation
}
public class TcpRequest : IRequest
{
// Implementation
}
One way could be to offer multiple methods. You can still hide the configuration but some implementation details leak into your client code.
public Interface IRequestFactory
{
IRequest CreateHttpRequest();
IRequest CreateTcpRequest();
}
public class RequestFactory : IRequestFactory
{
// Implementation
}
Another solution would be to determine whats needed while constructing your factory.
public Interface IRequestFactory
{
IRequest CreateRequest();
}
public class RequestFactory : IRequestFactory
{
private IConfigReader configReader;
public RequestFactory(IConfigReader configReader)
{
this.configReader = configReader;
}
public IRequest CreateRequest()
{
var currentProtocoll = configReader.GetCurrentProtocoll();
if(currentProtocoll is HTTP)
return new HttpRequest();
else
return new TcpRequest();
}
}
I would not recommend your solution with more factories. At least not with what you wrote so far.

What is the best way to implement Dependency Injection in Base Controller

I have the follow trouble, in my base controller i do dependency injection. And i have a class child with implementation of base controller and i need pass the constructor. So my doubt is, my way to implementation of dependency injection is correctly?
If no, what is the best way to do this?
I use unity to implementate D.I, and my ide is VS2017 web api 2.
Follow this code i using:
Base controller or parent controller:
public class BaseController : ApiController
{
public string[] includes = null;
private readonly IFiltroServico servico;
public BaseController(IFiltroServico _servico)
{
servico = _servico;
}
}
Base controller to generics types implements Base Controller:
public abstract class BaseController<E, R, F> : BaseController
where E : class
where R : class
where F : class
{
private readonly IFiltroServico servico;
public AreaFormacaoController(IFiltroServico _servico): base(_servico)
{
servico = _servico;
}
}
Child controller:
public abstract class BaseController<R> : BaseController
where R : class
{
private readonly IFiltroServico servico;
public AreaFormacaoController(IFiltroServico _servico): base(_servico)
{
servico = _servico;
}
//services of controller;
}
You don't need to define the private field servico over and over again as it is already preset in the base controller. Just define it as protected readonly in the base class and use it in the childs.
Other than that your code is fine.
It is perfectly reasonable that a child has the same dependency parameters in the constructor as it inherits behavior of the base class that is most likely relying on the dependency.
Another option would be to use property injection in the base class but you need to add a unity specific attribute to the property. I don't like that as you bind your code directly to Unity.
Have you seen https://simpleinjector.org/index.html
check out git from https://github.com/simpleinjector/SimpleInjector
It is one of the best Inversion of Control library (IOC).
Only thing you need to do is register all your services and types.
using SimpleInjector;
static class Program
{
static readonly Container container;
static Program() {
// 1. Create a new Simple Injector container
container = new Container();
// 2. Configure the container (register)
container.Register<IOrderRepository, SqlOrderRepository>();
container.Register<ILogger, FileLogger>(Lifestyle.Singleton);
container.Register<CancelOrderHandler>();
// 3. Verify your configuration
container.Verify();
}
static void Main(string[] args)) {
// 4. Use the container
var handler = container.GetInstance<CancelOrderHandler>();
var orderId = Guid.Parse(args[0]);
var command = new CancelOrder { OrderId = orderId };
handler.Handle(command);
}
}
Once you register all your types and services you can inject those services where ever you want
public class CancelOrderHandler {
private readonly IOrderRepository repository;
private readonly ILogger logger;
private readonly IEventPublisher publisher;
// Use constructor injection for the dependencies
public CancelOrderHandler(
IOrderRepository repository, ILogger logger, IEventPublisher publisher) {
this.repository = repository;
this.logger = logger;
this.publisher = publisher;
}
public void Handle(CancelOrder command) {
this.logger.Log("Cancelling order " + command.OrderId);
var order = this.repository.GetById(command.OrderId);
order.Status = OrderStatus.Cancelled;
this.repository.Save(order);
this.publisher.Publish(new OrderCancelled(command.OrderId));
}
}
public class SqlOrderRepository : IOrderRepository {
private readonly ILogger logger;
// Use constructor injection for the dependencies
public SqlOrderRepository(ILogger logger) {
this.logger = logger;
}
public Order GetById(Guid id) {
this.logger.Log("Getting Order " + order.Id);
// Retrieve from db.
}
public void Save(Order order) {
this.logger.Log("Saving order " + order.Id);
// Save to db.
}
}
Let me know if you have any queries, Thanks.

Implement controller with arguments in constructor

I have alot of not always static values (slogan, banner, description...) and PartialViews (block_head, block_footer, block_right), where i should display it. So, i need to pass big collection of this values into Partial in every Action and it's not very good for me.
I've found interesting solution here: http://www.asp.net/mvc/tutorials/passing-data-to-view-master-pages-cs , in part "Good solution". I could move all initialization of this values in ApplicationController and Implement it from my controllers.
But, i'd like to go forward and initialize my Interfaces in ApplicationController too :) If i could do it, i think it should be fantastic. I use Ninject, so, some code:
public abstract class ApplicationController : Controller
{
//
// GET: /Application/
private readonly IModuleRepository _moduleRepository;
public IModuleRepository moduleRepository
{
get { return _moduleRepository; }
}
public ApplicationController(IModuleRepository moduleRepository)
{
_moduleRepository = moduleRepository;
foreach (var module in _moduleRepository.GetAllModules())
ViewData[module.name] = module.value;
}
}
Implementing:
public class HomeController : ApplicationController
{
//I can use here moduleRepository without HomeController initialization
}
Just one problem, i don't know how to Implement ApplicationController, if it has arguments. Is it good way and is it any solution for my problem? In future i'm going to set 5-7 Interfaces and have about 10-15 Controllers, so it could be very good to Initialize them all in ApplicationController and Implement in other. Thx, sorry if the questiong is stupid.
Ok, adding:
Now, if i have 10 interfaces, it should be like this:
public class HomeController
{
private IModuleRepository _moduleRepository;
private IBookRepository _bookRepository;
private ITableRepository _tableRepository;
private IClassRepository _classRepository;
private IRoomRepository _roomRepository;
private IUserRepository _userRepository;
private IWindowRepository _windowRepository;
private IChairRepository _chairRepository;
private IDoorRepository _doorRepository;
private IWCRepository _wcRepository;
public HomeController(IModuleRepository moduleRepository, IBookRepository bookRepository, ITableRepository tableRepository, IClassRepository classRepository, IRoomRepository roomRepository, IUserRepository userRepository, IWindowRepository windowRepository, IChairRepository chairRepository, IDoorRepository doorRepository, IWCRepository wcRepository)
{
_moduleRepository = moduleRepository;
_bookRepository = bookRepository;
_tableRepository = tableRepository;
_classRepository = classRepository;
_roomRepository = roomRepository;
_userRepository = userRepository;
_windowRepository = windowRepository;
_chairRepository = chairRepository;
_doorRepository = doorRepository;
_wcRepository = wcRepository;
}
public ActionResult Index()
{
ViewBag.Windows = _windowRepository.GetAllWindows();
ViewBag.Doors = _doorRepository.GetAllDoors();
// e.t.c.
return View();
}
}
And i have to initialize this in each of my Controller, where i need to use this repositories (Home, Admin, ...).
So, if i could to make something like this:
public class HomeController : ApplicationController
{
public ActionResult Index()
{
ViewBag.Windows = windowRepository.GetAllWindows();
ViewBag.Doors = doorRepository.GetAllDoors();
return View();
}
}
And initialize just one time here:
public abstract class ApplicationController : Controller
{
public ApplicationController(IModuleRepository moduleRepository, IBookRepository bookRepository, ITableRepository tableRepository, IClassRepository classRepository, IRoomRepository roomRepository, IUserRepository userRepository, IWindowRepository windowRepository, IChairRepository chairRepository, IDoorRepository doorRepository, IWCRepository wcRepository)
{
// Initialize repositories just one time here
}
}
it could be very good, but i need to pass arguments in constructor of implementing class
It looks like you may be talking about Constructor Injection. The constructor of your sub type can invoke the constructor of your base type in order to inject the IModuleRepository
public class HomeController : ApplicationController
{
public HomeController(IModuleRepository moduleRepository) : base(moduleRepository)
{
//other constructor code here
}
public HomeController() : this(null)
{
//default constructor
}
}
public abstract class ApplicationController : Controller
{
public IModuleRepoistory _moduleRepository { get; private set; }
public ApplicationController(IModuleRepository moduleRepository)
{
_moduleRepository = moduleRepository ?? new DefaultModuleRepository();
//...
}
}
If in future you intend to inject a lot of interfaces then you'll probably be better off using Setter Injection
You could always use the Ninject dependency resolver to get the instance, so instead of_:
public ApplicationController(IModuleRepository moduleRepository, IBookRepository bookRepository, ITableRepository tableRepository, IClassRepository classRepository, IRoomRepository roomRepository, IUserRepository userRepository, IWindowRepository windowRepository, IChairRepository chairRepository, IDoorRepository doorRepository, IWCRepository wcRepository)
{
// Initialize repositories just one time here
}
you could do
protected readonly IModuleRepository ModuleRepository;
// same for the rest...
public ApplicationController()
{
this.ModuleRepository = MvcApplication.Container.Get<IModuleRepository>();
// same for rest or your modules.
}
if you're on MVC3 it would be:
protected readonly IModuleRepository ModuleRepository;
public ApplicationController()
{
this.ModuleRepository = DependencyResolver.Current.GetService<IModuleRepository>();
// same for rest or your modules.
}
Yeap, it's really better than first answer because now i have:
public abstract class ApplicationController : Controller
{
protected readonly IModuleRepository _moduleRepository;
public IModuleRepository moduleRepository
{
get { return _moduleRepository; }
}
public ApplicationController()
{
this._moduleRepository = DependencyResolver.Current.GetService<IModuleRepository>();
foreach (var module in _moduleRepository.GetAllModules())
ViewData[module.name] = module.value;
}
}
And i don't need to make any changes in my controllers. Just implement and could work with repositories:
public class HomeController : ApplicationController
{
public ActionResult Index()
{
ViewBag.Modules = moduleRepository.GetAllModules();
return View();
}
}
And in all of my Controllers i have full collection of ViewData values, which passing in PartialViews. Thx alot, awesome :) !

Categories