Constructor injection and initialization of dependencies being injected - c#

I am writing a simple console application that takes care of connecting to the database, selecting a particular product from it (based on the provided criteria) and doing some processing with this product. I am storing command-line arguments to an instance of this class:
public class Arguments
{
public string ConnectionString { get; set; }
public int ProductId { get; set; }
public string ProductName { get; set; }
}
At some point, I need to fetch the product from the database. I am using the following repository for that:
public interface IProductRepository
{
Product GetById(int productId, string connectionString);
Product GetByName(string productName, string connectionString);
}
Then, I inject an implementation of the repository to the class that uses it, e.g:
public class ProductProcessor
{
private readonly IProductRepository productRepository;
public ProductProcessor(IProductRepository productRepository)
{
this.productRepository = productRepository;
}
public void Process(Arguments arguments)
{
Product productToProcess;
if (!string.IsNullOrEmpty(arguments.ProductName))
{
productToProcess = productRepository.GetByName(arguments.ProductName, arguments.ConnectionString);
}
else
{
productToProcess = productRepository.GetById(arguments.ProductId, arguments.ConnectionString);
}
// ....
}
}
This is working, but what I don't like about the design is that every method of the IProductRepository has a connectionString argument. If there was no dependency injection involved, I would probably rewrite it like the following:
public void Process(Arguments arguments)
{
Product productToProcess;
ProductRepository productRepository = new ProductRepository(arguments.ConnectionString);
if (!string.IsNullOrEmpty(arguments.ProductName))
{
productToProcess = productRepository.GetByName(arguments.ProductName);
}
else
{
productToProcess = productRepository.GetById(arguments.ProductId);
}
// ....
}
This enables me to have simpler and easier-to-use interface. Of course, now the ProductRepository does not have parameterless constructor and it is difficult to use with DI container. Ideally, I would like to have the best of both worlds, i.e. to initialize the ProductRepository with the connection string from constructor and remove the connection string from its methods. What is the best approach to achieve this?
Some approaches I've already considered:
Add a method Initialize(string connectionString) to the IProductRepository that would basically serve as a constructor. Obvious drawback is that I now need to check whether the Initialize has been called before doing anything in GetById or GetByName methods.
Do not use constructor injection and use Service Locator pattern instead to instantiate ProductRepository. I don't like Service Locator much, but this is probably only possible solution.
Is there any better alternative?
EDIT: From the answers I see that I should have posted a bit more context. I am using Ninject as my DI container. In Main method in my Program.cs, I register all dependencies to the container and instantiate the class that serves as an entry-point to the application:
public static void Main(string[] args)
{
StandardKernel kernel = new StandardKernel();
kernel.Bind<IArgumentsParser>().To<IArgumentsParser>();
kernel.Bind<IProductProcessor>().To<ProductProcessor>();
kernel.Bind<IProductRepository>().To<ProductRepository>();
MainClass mainClass = kernel.Get<MainClass>();
mainClass.Start(args);
}
The MainClass looks like the following:
public class MainClass
{
private readonly IArgumentsParser argumentsParser;
private readonly IProductProcessor productProcessor;
public MainClass(IArgumentsParser parser, IProductProcessor processor)
{
argumentsParser = parser;
productProcessor = processor;
}
public void Start(string[] args)
{
Arguments parsedArguments = argumentsParser.Parse(args);
productProcessor.Process(parsedArguments );
}
}
This enables me to have a dependency to Ninject and creation of the whole graph in one place only (the Main method) and the rest of the application knows nothing about DI and containers.
I'd like to keep it that way, if possible.

I agree that the current interface design is a leaky abstraction, so let's define it like this instead:
public interface IProductRepository
{
Product GetById(int productId);
Product GetByName(string productName);
}
What you need then is an Abstract Factory that can create an instance of IProductRepository for you.
So ProductProcessor could look like this:
public class ProductProcessor
{
private readonly IProductRepositoryFactory productRepositoryFactory;
public ProductProcessor(IProductRepositoryFactory productRepositoryFactory)
{
this.productRepositoryFactory = productRepositoryFactory;
}
public void Process(Arguments arguments)
{
Product productToProcess;
var productRepository =
this.productRepositoryFactory.Create(arguments.ConnectionString);
if (!string.IsNullOrEmpty(arguments.ProductName))
{
productToProcess = productRepository.GetByName(arguments.ProductName);
}
else
{
productToProcess = productRepository.GetById(arguments.ProductId);
}
// ....
}
}

I'm not sure why you need to model the command line arguments at all? You should minimize the dependencies on each of your types. This means the product repository should take the connection string as a constructor parameter (because it's a required dependency), and your product processor should take the product id and product name (if this is the best way you feel to do dynamic queries).
Therefore, assuming your product repository is a singleton, you would new it up at the point you do your registrations (passing in the connection string), and then register this in your IoC container against your abstraction.
You could then new up a product processor (passing in the product id and product name) and register this as singleton against an abstraction. You can then use constructor injection to pass the product processor into any type that requires it.

Of course, now the ProductRepository does not have parameterless
constructor and it is difficult to use with DI container.
On the contrary, most DI containers allow you to work with parameterized constructors. In fact, when doing Dependency Injection, constructor injection is the advised approach, which means you will have non-default constructors. Having a constructor that takes in a primitive type (such as a string dependency), might mean that some containers won't be able to do auto-wiring for you. Auto-wiring means that the container will figure out what to inject. However, with your product repository, this problem can easily be solved by supplying a initialized instance to the container (if you need a single instance), or supplying a factory delegate (if you need a new instance on each call). It depends on which framework you use, but it might look like this:
container.RegisterSingle(new SqlProductFactory("constring"));
When you supply the connection string in the SqlProductFactory's constructor, you won't have to pass it in (using method injection) to the factory, and you don't need this connection string in your Arguments class.

What you can do is to decouple object creation from object look up. The DI container will look up for instance you have registered at the start up. At that point you can pass in the connection string as a constructor argument to your repository.
This is how the product code would look like;
public class ProductRepository : IProductRepority
{
private readonly string connString;
public ProductRepository(string conn)
{
connString = conn;
}
}
You can wrap connection string with another type too if needed. The important point is, DI will inject instances required based on the binding done at the type graph during start up. Based on the registration you can simply extract connection string from the args and pass it along the ProductRepository registration.

EDIT
See the following answer for how to solve you stated problem.
However, I would really recommend using an existing IOC package, such as Windsor or nHibernate. See https://stackoverflow.com/questions/2515124/whats-the-simplest-ioc-container-for-c for some details.
END EDIT
Why not add ConnectionString as a Property to IProductRepository.
So the interface is:
public interface IProductRepository
{
string ConnectionString { get; set; }
Product GetById(int productId);
Product GetByName(string productName);
}
And the processor becomes:
public void Process(Arguments arguments)
{
Product productToProcess;
var productRepository = new ProductRepository
{ ConnectionString = arguments.ConnectionString};
if (!string.IsNullOrEmpty(arguments.ProductName))
productToProcess = productRepository.GetByName(arguments.ProductName);
else
productToProcess = productRepository.GetById(arguments.ProductId);
// ....
}

Related

C# Web API Runtime Data with Dependency Injection

If I have a service that relies on data obtained through runtime, what is the best way to inject it into a class?
I have an Order class:
class Order {
string OrderID { get; set; }
string CustomerName { get; set; }
...
}
I want to encapsulate a lot of logic from the database, so I have a service:
class OrderService {
private readonly IOrderRepository _orderRepository;
private readonly IOrder _order;
public OrderService(IOrderRepository orderRepository, IOrder order) {
_orderRepository = orderRepository;
_order = order;
}
// some methods that compile data from the repository
public bool CheckAlreadyExists() { ... }
public string GetLatestShippingStatus() { ... }
...
...
public void Create() { ... }
}
Controller logic:
public class OrderController {
private readonly IOrderRepository _orderRepository
public OrderController(IOrderRepository orderRepository)
{
orderRepository = _orderRepository
}
public IActionResult Create(Order order)
// this is bad because now I have a dependency on IOrderRepository and OrderService
OrderService orderService = new OrderService(orderRepository, order)
if (!orderService.CheckAlreadyExists()) {
orderService.Create();
}
end
}
The two options I am aware of:
Refactor the code to pass runtime data into each of the functions instead
Create a factory OrderServiceFactory
I do not want to have to pass the parameter into every method which all rely on the same object. It seems like overkill to create a factory for every time I need this pattern, which seems like it should be a common use-case.
I think I'm fundamentally misunderstanding something.
Is there a pattern that I'm unaware of?
Could I create a service that keeps track of the runtime data?
Or am I just being stubborn and should create a factory?
I would simply comment but I don't have the reputation. Long story short, you need to be passing runtime data to OrderService. Read the link provided by Nkosi.
Having OrderService instantiated with a particular Order does not make sense. That means that you have to new up OrderService for every Order you get. Instead, OrderService should have per-lifetime scope. Ie - you can use the same instance of OrderService with multiple Orders. It's not overkill to pass runtime data to every method of a service; it's standard. You're overcomplicating things by forcing your service to rely on an instance of the object it is servicing. And your OrderRepository should not be injected in your controller at all. Use the service to call repository methods.

Cannot access appsettings.json from class library

I have been following this tutorial in order to get access to my appsettings.json from my MVC project inside my class library.
geek-tutorial
I have a class as such in my class library
using dapper;
public class SqlDataAccess : IConfigManager
{
private readonly IConfiguration _configuration;
public SqlDataAccess(IConfiguration configuration)
{
this._configuration = configuration;
}
public List<T> LoadData<T>(string sql)
{
using (IDbConnection cnn = new SqlConnection(GetConnectionString()))
{
return cnn.Query<T>(sql).ToList();
}
}
public int SaveData<T>(string sql, T data)
{
using (IDbConnection cnn = new SqlConnection(GetConnectionString()))
{
return cnn.Execute(sql, data);
}
}
public string GetConnectionString(string connectionName = "URLShortnerDB")
{
return this._configuration.GetConnectionString(connectionName);
}
}
Interface:
public interface IConfigManager
{
string GetConnectionString(string connectionName);
}
I have added services.AddSingleton<IConfigManager, SqlDataAccess>(); in my mvc startup.cs
However now I would like to use my SqlDataAccess class and call methods from another class e.g:
public static class ShortUrlProcessor
{
public static ShortURLModel GetOriginalURL(string shortUrl)
{
string sql = $#"SELECT * FROM dbo.shorturl WHERE shortUrl = '{ shortUrl }'";
var originalURLEnum = SqlDataAccess.LoadData<ShortURLModel>(sql); //<--- problem
return originalURLEnum.First();
}
}
However SqlDataAccess is not instantiated, and in order to do var _sqldataaccess = SqlDataAccess() I need to pass in a parameter as defined in the constructor of the class. I do not know what to pass in? I do not have any IconfigurationManager in this ShortUrlProcessor class. I understand the reason of doing this is dependancy injection, however I am still not grasping how this all works?
You're very close, but you need to fix a few things. SqlDataAccess implements IConfigManager. Why? What's that providing? Instead, you should have it implement an interface that allows it to expose the functionality other classes depend on.
public interface ISqlDataAccess
{
List<T> LoadData<T>(string sql);
int SaveData<T>(string sql, T data);
}
Change your SqlDataAccess class to implement this interface...
public class SqlDataAccess : ISqlDataAccess
And of course, wire this up with your DI container.
services.AddTransient<ISqlDataAccess, SqlDataAccess>();
Now, any class that needs to run SQL can take a dependency on the ISqlDataAccess interface, utilizing constructor injection to get an instance of ISqlDataAccess. Since we've told the DI container to provide a SqlDataAccess instance when the ISqlDataAccess dependency is present, it will all wire up nicely in your app.
Then we have the issue with ShortUrlProcessor. You declared that class as static. That's bad, because it makes it difficult for it to use constructor injection to get its dependencies, and any other class that needs to invoke its methods has to do so directly, rather than via an abstraction. That violates the Dependency Inversion Principle of SOLID. And since we should always strive to write SOLID code because of the maintainability and testability, we need to fix that.
public class ShortUrlProcessor : IShortUrlProcessor
{
readonly ISqlDataAccess _dataAccess;
public ShortUrlProcessor(ISqlDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
public ShortURLModel GetOriginalURL(string shortUrl)
{
string sql = $#"SELECT * FROM dbo.shorturl WHERE shortUrl = '{ shortUrl }'";
var originalURLEnum = _dataAccess.LoadData<ShortURLModel>(sql); //<--- problem
return originalURLEnum.First();
}
}
And we'll need an interface so other classes don't have to depend directly on ShortUrlProcessor...
public interface IShortUrlProcessor
{
ShortURLModel GetOriginalURL(string shortUrl);
}
And of course, we need to register it with our DI container.
services.AddTransient<IShortUrlProcessor, ShortUrlProcessor>();
Then any class that needs to access the functionality of ShortUrlProcessor can do so via the abstraction IShortUrlProcessor. You mentioned you have a controller calling this, so let's wire that up too.
public class MyController()
{
readonly IShortUrlProcessor _shortUrlProcessor;
public MyController(IShortUrlProcessor shortUrlProcessor)
{
_shortUrlProcessor = shortUrlProcessor;
}
public ActionResult SomeActionMethod()
{
var model = _shortUrlProcessor.GetOriginalURL("asdf");
return View(model);
}
}
We don't have to create an interface for the controller, because the controller will be called by the framework. And we don't have to wire up the controller with the DI container, because the framework handles that for us.
By doing all this, we can easily test individual methods in isolation. There's still some improvements to be made (the SQL Injection attack I mentioned in the comments needs to be fixed), but it's a good step in the right direction.

Determining which implementation to inject at runtime using .NET Core dependency injection

I have three types of users in my application, let's say Type1, Type2 and Type3.
Then i want to create one service implementation for each type, let's say i have a service to get photos, i would have three services : Type1PhotosService, Type2PhotosService and Type3PhotosService, each of them implementing IPhotosService.
In the web api, i would inject IPhotosService :
IPhotosService _service;
public PhotosController(IPhotosService service){
_service = service;
}
The web api uses token authentication with claims. So what i want to achieve, is for each user, depending on the claim he has : type1 or type2 or type3, the correct implementation of the service will be automatically injected rather than injecting a single service in the startup file.
What i want to avoid, is having one service, with a bunch of switch and if statements to return the correct data depending on user type and the roles he has.
EDIT:
some comments were wondering what's the point of three implementations, so here are more details to give it a little more sense.
The service is a job finder service, and the application has three different profiles : candidate, employer and administration. Each of these profiles need a proper implementation. So rather than having three methods GetCandidateJobs, GetEmployerJobs and GetAdministrationJobs inside the same service and switch on the user type, i preferred to have one implementation per profile type, then depending on the profile type, use the correct implementation.
Without Using a Separate IoC Container
Here's an approach that's way easier than configuring your app to use another IoC container and then configuring that container. After working through this with Windsor this solution seems a whole lot easier.
This approach is simplest if you can use a singleton instance of each service implementation.
We'll start with an interface, some implementations, and the factory we can inject which will return an implementation selected at runtime based on some input.
public interface ICustomService { }
public class CustomServiceOne : ICustomService { }
public class CustomServiceTwo : ICustomService { }
public class CustomServiceThree : ICustomService { }
public interface ICustomServiceFactory
{
ICustomService Create(string input);
}
Here's a really crude implementation of the factory. (Didn't use string constants, or polish it at all.)
public class CustomServiceFactory : ICustomServiceFactory
{
private readonly Dictionary<string, ICustomService> _services
= new Dictionary<string, ICustomService>(StringComparer.OrdinalIgnoreCase);
public CustomServiceFactory(IServiceProvider serviceProvider)
{
_services.Add("TypeOne", serviceProvider.GetService<CustomServiceOne>());
_services.Add("TypeTwo", serviceProvider.GetService<CustomServiceTwo>());
_services.Add("TypeThree", serviceProvider.GetService<CustomServiceThree>());
}
public ICustomService Create(string input)
{
return _services.ContainsKey(input) ? _services[input] : _services["TypeOne"];
}
}
This assumes that you've already registered CustomServiceOne, CustomServiceTwo, etc. with the IServiceCollection. They would not be registered as interface implementations, since that's not how we're resolving them. This class will simply resolve each one and put them in a dictionary so that you can retrieve them by name.
In this case the factory method takes a string, but you could inspect any type or multiple arguments to determine which implementation to return. Even the use of a string as the dictionary key is arbitrary. And, just as an example, I provided fallback behavior to return some default implementation. It might make more sense to throw an exception instead if you can't determine the right implementation to return.
Another alternative, depending on your needs, would be to resolve the implementation within the factory when it's requested. To the extent possible I try to keep most classes stateless so that I can resolve and reuse a single instance.
To register the factory with the IServiceCollection at startup we would do this:
services.AddSingleton<ICustomServiceFactory>(provider =>
new CustomServiceFactory(provider));
The IServiceProvider will be injected into the factory when the factory is resolved, and then the factory will use it to resolve the service.
Here's the corresponding unit tests. The test method is the identical to the one used in the Windsor answer, which "proves" that we can transparently replace one factory implementation with another and change other stuff in the composition root without breaking stuff.
public class Tests
{
private IServiceProvider _serviceProvider;
[SetUp]
public void Setup()
{
var services = new ServiceCollection();
services.AddSingleton<CustomServiceOne>();
services.AddSingleton<CustomServiceTwo>();
services.AddSingleton<CustomServiceThree>();
services.AddSingleton<ICustomServiceFactory>(provider =>
new CustomServiceFactory(provider));
_serviceProvider = services.BuildServiceProvider();
}
[TestCase("TypeOne", typeof(CustomServiceOne))]
[TestCase("TypeTwo", typeof(CustomServiceTwo))]
[TestCase("TYPEThree", typeof(CustomServiceThree))]
[TestCase("unknown", typeof(CustomServiceOne))]
public void FactoryReturnsExpectedService(string input, Type expectedType)
{
var factory = _serviceProvider.GetService<ICustomServiceFactory>();
var service = factory.Create(input);
Assert.IsInstanceOf(expectedType, service);
}
}
As in the Windsor example, this is written to avoid any reference to the container outside of the composition root. If a class depends on ICustomServiceFactory and ICustomService you could switch between this implementation, the Windsor implementation, or any other implementation of the factory.
Using Windsor
I'm going to sidestep the questions about whether or not this makes sense in this case and just attempt to answer the question as asked:
.NET Core's IoC container isn't built particularly well for this sort of scenario. (They acknowledge this in their documentation.) You can work around it by adding another IoC container like Windsor.
The implementation ended up looking way more complicated than I would have liked, but once you get past the setup it's not bad and you get access to Windsor's features. I'm going to provide another answer that doesn't include Windsor. I had to do all of this work to see that I probably like the other approach better.
In your project, add the Castle.Windsor.MsDependencyInjection NuGet package.
Interfaces and Implementations for Testing
For testing, I added some interfaces and implementations:
public interface ICustomService { }
public interface IRegisteredWithServiceCollection { }
public class CustomServiceOne : ICustomService { }
public class CustomServiceTwo : ICustomService { }
public class CustomServiceThree : ICustomService { }
public class RegisteredWithServiceCollection : IRegisteredWithServiceCollection { }
The intent is to create a factory that will select and return an implementation of ICustomService using some runtime input.
Here's an interface which will serve as a factory. This is what we can inject into a class and call at runtime to get an implementation of ICustomService:
public interface ICustomServiceFactory
{
ICustomService Create(string input);
}
Configure the Windsor Container
Next is a class which will configure an IWindsorContainer to resolve dependencies:
public class WindsorConfiguration : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<ICustomService, CustomServiceOne>().Named("TypeOne"),
Component.For<ICustomService, CustomServiceTwo>().Named("TypeTwo"),
Component.For<ICustomService, CustomServiceThree>().Named("TypeThree"),
Component.For<ICustomService, CustomServiceOne>().IsDefault(),
Component.For<ICustomServiceFactory>().AsFactory(new CustomServiceSelector())
);
}
}
public class CustomServiceSelector : DefaultTypedFactoryComponentSelector
{
public CustomServiceSelector()
: base(fallbackToResolveByTypeIfNameNotFound: true) { }
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
return (string) arguments[0];
}
}
Here's what's going on in here:
The TypedFactoryFacility will enable us to use Windsor's typed factories. It will create an implementation of our factory interface for us.
We're registering three implementations of ICustomService. Because we're registering more than one implementation, each must have a name. When we resolve ICustomService we can specify a name, and it will resolve the type according to that string.
For illustration I registered another implementation of ICustomService without a name. That will enable us to resolve a default implementation if we try to resolve using an unrecognized name. (Some alternatives are just throwing an exception, or returning a "null" instance of ICustomService or creating a class like UnknownCustomService that throws an exception.)
Component.For<ICustomServiceFactory>().AsFactory(new CustomServiceSelector()) tells the container to create a proxy class to implement ICustomServiceFactory. (More on that in their documentation.)
CustomServiceSelector is what takes the argument passed to the factory's Create method and returns the component name (TypeOne, TypeTwo, etc.) that will be used to select a component. In this case we're expecting that the argument passed to the factory will be the same as the registration name we've used. But we could replace this with other logic. Our factory could even take arguments of other types which we could inspect and determine which string to return.
Configure Your App To Use the Windsor Container
Now, in StartUp, modify ConfigureServices to return IServiceProvider instead of void and create an IServiceProvider that combines services registered directly with the IServiceCollection with those registered with the Windsor container:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var container = new WindsorContainer();
container.Install(new WindsorConfiguration());
return WindsorRegistrationHelper.CreateServiceProvider(container, services);
}
container.Install(new WindsorConfiguration()) allows WindsorConfiguration to configure our container. We could just configure the container right in this method, but this is a nice way to keep our container configurations organized. We can create numerous IWindsorInstaller implementations or our own custom classes to configure the Windsor container.
WindsorRegistrationHelper.CreateServiceProvider(container, services) creates the IServiceProvider that uses container and services.
Does It Work?
I wouldn't post all this without finding out first. Here's some NUnit tests. (I usually write some basic tests for DI configuration.)
The setup creates an IServiceProvider similar to what would happen in the application startup. It creates a container and applies the WindsorConfiguration. I'm also registering a service directly with the ServiceCollection to make sure that the two play well together. Then I'm combining the two into an IServiceProvider.
Then I'm resolving an ICustomerServiceFactory from the IServiceProvider and verifying that it returns the correct implementation of ICustomService for each input string, including the fallback when the string isn't a recognized dependency name.
I'm also verifying that the service registered directly with ServiceCollection is resolved.
public class Tests
{
private IServiceProvider _serviceProvider;
[SetUp]
public void Setup()
{
var services = new ServiceCollection();
services.AddSingleton<IRegisteredWithServiceCollection, RegisteredWithServiceCollection>();
var container = new WindsorContainer();
container.Install(new WindsorConfiguration());
_serviceProvider = WindsorRegistrationHelper.CreateServiceProvider(container, services);
}
[TestCase("TypeOne", typeof(CustomServiceOne))]
[TestCase("TypeTwo", typeof(CustomServiceTwo))]
[TestCase("TYPEThree", typeof(CustomServiceThree))]
[TestCase("unknown", typeof(CustomServiceOne))]
public void FactoryReturnsExpectedService(string input, Type expectedType)
{
var factory = _serviceProvider.GetService<ICustomServiceFactory>();
var service = factory.Create(input);
Assert.IsInstanceOf(expectedType, service);
}
[Test]
public void ServiceProviderReturnsServiceRegisteredWithServiceCollection()
{
var service = _serviceProvider.GetService<IRegisteredWithServiceCollection>();
Assert.IsInstanceOf<RegisteredWithServiceCollection>(service);
}
}
Is All of This Worth It?
Now that I've figured it out, I'd probably use it if I really needed this sort of functionality. It looks worse if you're trying to assimilate both using Windsor with .NET Core and seeing it's abstract factory implementation for the first time. Here's another article with some more information on Windsor's abstract factory without all the noise about .NET Core.
I am going to go out on a limb here and say that the attempt to utilize dependency injection for this purpose is sub-optimal. Normally this would be handled by a Factory pattern that produces service implementations using the dreaded if and switch statements. A simple example is:
public interface IPhotoService {
Photo CreatePhoto(params);
}
public class PhotoServiceFactory {
private readonly IPhotoService _type1;
private readonly IPhotoService _type2;
private readonly IPhotoService _type3;
public PhotoServiceFactory(IDependency1 d1, IDependency2 d2, ...etc) {
_type1 = new ConcreteServiceA(d1);
_type2 = new ConcreteServiceB(d2);
_type3 = new ConcreteServiceC(etc);
}
public IPhotoService Create(User user) {
switch(user.Claim) {
case ClaimEnum.Type1:
return _type1;
case ClaimEnum.Type2:
return _type2;
case ClaimEnum.Type3:
return _type3;
default:
throw new NotImplementedException
}
}
}
Then in your controller:
public class PhotosController {
IPhotoServiceFactory _factory;
public PhotosController(IPhotoServiceFactory factory){
_factory = factory;
}
public IHttpActionResult GetPhoto() {
var photoServiceToUse = _factory.Create(User);
var photo = photoServiceToUse.CreatePhoto(params);
return Ok(photo);
}
}
Alternately just use the concrete classes as arguments in the constructor and follow a similar logic as to the above.
Here is one solution, i have created inside asp.net core console application.
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
namespace CreationalPattern
{
class Program
{
static void Main(string[] args)
{
// Add dependency into service collection
var services = new ServiceCollection()
.AddTransient<FordFigoFactory>()
.AddTransient<AudiQ7Factory>();
/* Create CarServiceFactory as singleton because it can be used across the application more frequently*/
services.AddSingleton<ICarServiceFactory>(provider => new CarServiceFactory(provider));
// create a service provider from the service collection
var serviceProvider = services.BuildServiceProvider();
/* instantiate car*/
var factory = serviceProvider.GetService<ICarServiceFactory>();
var audiCar = factory.Create("audi").CreateACar("Blue");
Console.Read();
}
}
public interface ICarServiceFactory
{
ICreateCars Create(string input);
}
public class CarServiceFactory : ICarServiceFactory
{
private readonly Dictionary<string, ICreateCars> _services
= new Dictionary<string, ICreateCars>(StringComparer.OrdinalIgnoreCase);
public CarServiceFactory(IServiceProvider serviceProvider)
{
_services.Add("ford", serviceProvider.GetService<FordFigoFactory>());
_services.Add("audi", serviceProvider.GetService<AudiQ7Factory>());
}
public ICreateCars Create(string input)
{
Console.WriteLine(input + " car is created.");
return _services.ContainsKey(input) ? _services[input] : _services["ford"];
}
}
public interface ICreateCars
{
Car CreateACar(string color);
}
public class FordFigoFactory : ICreateCars
{
public Car CreateACar(string color)
{
Console.WriteLine("FordFigo car is created with color:" + color);
return new Fordigo { Color = color};
}
}
public class AudiQ7Factory : ICreateCars
{
public Car CreateACar(string color)
{
Console.WriteLine("AudiQ7 car is created with color:" + color);
return new AudiQ7 { Color = color };
}
}
public abstract class Car
{
public string Model { get; set; }
public string Color { get; set; }
public string Company { get; set; }
}
public class Fordigo : Car
{
public Fordigo()
{
Model = "Figo";
Company = "Ford";
}
}
public class AudiQ7 : Car
{
public AudiQ7()
{
Model = "Audi";
Company = "Q7";
}
}
}
Explanation:
To understand better try to read the program from bottom to top. We have 3 sections:
Car (Car, Fordigo, AudiQ7)
CarFactory (ICreateCars, FordFigoFactory, AudiQ7Factory)
CarService (ICarServiceFactory, CarServiceFactory)
In this Dependency injection is registered as transient for Factory classes FordFigoFactory and AudiQ7Factory. And Singleton for CarServiceFactory.

Property / method injection using Autofac in filter attributes

Trying to use autofac for dependency injection by property.
The instance is always null and there is no dependency injected.
Below is class where the property needs to be injected.
public class UserAccount
{
public IAccountService AccountService { get; set; }
public string Message()
{
return AccountService.Message();
}
}
I have tried three different ways to inject the property but none was successful
Method 1 :
builder.Register(c => {
var result = new UserAccount();
var dep = c.Resolve<IAccountService>();
result.SetDependency(dep);
return result;
});
Method 2 :
builder.RegisterType<UserAccount>().PropertiesAutowired();
Method 3 :
builder.Register(c => new UserAccount { AccountService = c.Resolve<IAccountService>()});
PS : Method injection of above is welcomed.
You should prevent letting your container create data-centric objects, such as your UserAccount entity. This leads to complicated scenarios, such as the one you are in now.
In general, your DI Container should resolve only components—those are the classes in your system that contain the application's behavior, without having any interesting state. Those types of classes are typically long lived, or at least, longer lived than data-centric objects.
Data-centric objects, like entities, can best be created by hand. Not doing so would either lead to entities with big constructors, which easily causes the constructor over-injection code smell. As remedy, you might fall back on using Property Injection, but this causes a code smell of its own, caused Temporal Coupling.
Instead, a better solution is to:
Create entities by hand, opposed to using a DI Container
Supply dependencies to the entity using Method Injection, opposed to using Property Injection
With Method Injection, your UserAccount would as follows:
// This answer assumes that this class is an domain entity.
public class UserAccount
{
public Guid Id { get; set; }
public byte[] PasswordHash { get; set; }
public string Message(IAccountService accountService)
{
if (accountService == null)
throw new ArgumentNullException(nameof(accountService));
return accountService.Message();
}
}
This does move the responsibility of supplying the dependency from the Composition Root to the entity's direct consumer, though. But as discussed above, this is intentional, as the Composition Root in general, and a DI Container in particular, should not be responsible of creating entities and other data-centric, short-lived objects.
This does mean, however, that UserAccount's direct consumer should inject that dependency, and with that, know about existence of the dependency. But as that consumer would be a behavior-centric class, the typical solution is to use Constructor Injection at that stage:
public class UserService : IUserService
{
private readonly IAccountService accountService;
private readonly IUserAccountRepository repo;
public UserService(IAccountService accountService, IUserAccountRepository repo)
{
this.accountService = accountService;
this.repo = repo
}
public void DoSomething(Guid id)
{
UserAccount entity = this.repo.GetById(id);
var message = entity.Message(this.accountService);
}
}
Using method 3, you need to register AccountService, i.e.
builder.RegisterType<AccountService>().As<IAccountService>();
builder.Register(c => new UserAccount { AccountService = c.Resolve<IAccountService>()});
And when you use UserAccount, make sure it is created using Autofac.

Dependency Injection in Model classes (entities)

I am building an ASP.NET Core MVC application with Entity Framework Code-First.
I implemented a simple repository pattern, providing basic CRUD operations for all the model classes I have created.
I chose to follow all the recommendations provided in docs and DI is one of these.
In ~~.NET 5~~ (6 years later update: .net 5 was the alpha name of .net core 1.0) dependency injection works very well for any class that we do not directly instantiate (e.g.: controllers, data repositories, ...).
We simply inject them via the constructor, and register the mappings in the Startup class of the application :
// Some repository class
public class MyRepository : IMyRepository
{
private readonly IMyDependency _myDependency;
public MyRepository(IMyDependency myDependency)
{
_myDependency = myDependency;
}
}
// In startup.cs :
services.AddScoped<IMyDependency, MyDependency>();
services.AddScoped<IMyRepository, MyRepository>();
The problem is that in some of my model classes, I would like to inject some of the dependencies I have declared.
But I think that I cannot use the constructor injection pattern because model classes are often explicitly instantiated. Therefore, I would need to provide myself with the dependencies, which I can't.
So my question is: is there another way than constructor injection to inject dependencies, and how? I was for example thinking of an attribute pattern or something like that.
As I already explained in a comment, when creating an object using new, there is nothing from the dependency injection framework that is involved in the process. As such, it’s impossible for the DI framework to magically inject things into that object, it simply doesn’t know about it.
Since it does not make any sense to let the DI framework create your model instances (models are not a dependency), you will have to pass in your dependencies explicitly if you want the model to have them. How you do that depends a bit on what your models are used for, and what those dependencies are.
The simple and clear case would be to just have your model expect the dependencies on the constructor. That way, it is a compile time error if you do not provide them, and the model has access to them right away. As such, whatever is above, creating the models, is required to have the dependencies the model type needs. But at that level, it’s likely that this is a service or a controller which has access to DI and can request the dependency itself.
Of course, depending on the number of dependencies, this might become a bit complicated as you need to pass them all to the constructor. So one alternative would be to have some “model factory” that takes care of creating the model object. Another alternative would also be to use the service locator pattern, passing the IServiceCollection to the model which can then request whatever dependencies it needs. Note that is generally a bad practice and not really inversion of control anymore.
Both these ideas have the issue that they modify the way the object is created. And some models, especially those handled by Entity Framework, need an empty constructor in order for EF to be able to create the object. So at that point you will probably end up with some cases where the dependencies of your model are not resolved (and you have no easy way of telling).
A generally better way, which is also a lot more explicit, would be to pass in the dependency where you need it, e.g. if you have some method on the model that calculates some stuff but requires some configuration, let the method require that configuration. This also makes the methods easier to test.
Another solution would be to move the logic out of the model. For example the ASP.NET Identity models are really dumb. They don’t do anything. All the logic is done in the UserStore which is a service and as such can have service dependencies.
The pattern often used in domain driven design (rich domain model to be specific) is to pass the required services into the method you are calling.
For example if you want to calculate the vat, you'd pass the vat service into the CalculateVat method.
In your model
public void CalculateVat(IVatCalculator vatCalc)
{
if(vatCalc == null)
throw new ArgumentNullException(nameof(vatCalc));
decimal vatAmount = vatcalc.Calculate(this.TotalNetPrice, this.Country);
this.VatAmount = new Currency(vatAmount, this.CurrencySymbol);
}
Your service class
// where vatCalculator is an implementation IVatCalculator
order.CalculateVat(vatCalculator);
Finally your service can inject another services, like a repository which will fetch the tax rate for a certain country
public class VatCalculator : IVatCalculator
{
private readonly IVatRepository vatRepository;
public VatCalculator(IVatRepository vatRepository)
{
if(vatRepository == null)
throw new ArgumentNullException(nameof(vatRepository));
this.vatRepository = vatRepository;
}
public decimal Calculate(decimal value, Country country)
{
decimal vatRate = vatRepository.GetVatRateForCountry(country);
return vatAmount = value * vatRate;
}
}
I know my answer is late and may not exactly what you're asking for, but I wanted to share how I do it.
First of all: If you want to have a static class that resolves your dependencies this is a ServiceLocator and it's Antipattern so try not to use it as you can.
In my case I needed it to call MediatR inside of my DomainModel to implement the DomainEvents logic.
Anyway, I had to find a way to call a static class in my DomainModel to get an instance of some registered service from DI.
So I've decided to use the HttpContext to access the IServiceProvider but I needed to access it from a static method without mention it in my domain model.
Let's do it:
1- I've created an interface to wrap the IServiceProvider
public interface IServiceProviderProxy
{
T GetService<T>();
IEnumerable<T> GetServices<T>();
object GetService(Type type);
IEnumerable<object> GetServices(Type type);
}
2- Then I've created a static class to be my ServiceLocator access point
public static class ServiceLocator
{
private static IServiceProviderProxy diProxy;
public static IServiceProviderProxy ServiceProvider => diProxy ?? throw new Exception("You should Initialize the ServiceProvider before using it.");
public static void Initialize(IServiceProviderProxy proxy)
{
diProxy = proxy;
}
}
3- I've created an implementation for the IServiceProviderProxy which use internally the IHttpContextAccessor
public class HttpContextServiceProviderProxy : IServiceProviderProxy
{
private readonly IHttpContextAccessor contextAccessor;
public HttpContextServiceProviderProxy(IHttpContextAccessor contextAccessor)
{
this.contextAccessor = contextAccessor;
}
public T GetService<T>()
{
return contextAccessor.HttpContext.RequestServices.GetService<T>();
}
public IEnumerable<T> GetServices<T>()
{
return contextAccessor.HttpContext.RequestServices.GetServices<T>();
}
public object GetService(Type type)
{
return contextAccessor.HttpContext.RequestServices.GetService(type);
}
public IEnumerable<object> GetServices(Type type)
{
return contextAccessor.HttpContext.RequestServices.GetServices(type);
}
}
4- I should register the IServiceProviderProxy in the DI like this
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddSingleton<IServiceProviderProxy, HttpContextServiceProviderProxy>();
.......
}
5- Final step is to initialize the ServiceLocator with an instance of IServiceProviderProxy at the Application startup
public void Configure(IApplicationBuilder app, IHostingEnvironment env,IServiceProvider sp)
{
ServiceLocator.Initialize(sp.GetService<IServiceProviderProxy>());
}
As a result now you can call the ServiceLocator in your DomainModel classes "Or and needed place" and resolve the dependencies that you need.
public class FakeModel
{
public FakeModel(Guid id, string value)
{
Id = id;
Value = value;
}
public Guid Id { get; }
public string Value { get; private set; }
public async Task UpdateAsync(string value)
{
Value = value;
var mediator = ServiceLocator.ServiceProvider.GetService<IMediator>();
await mediator.Send(new FakeModelUpdated(this));
}
}
The built-in model binders complain that they cannot find a default ctor. Therefore you need a custom one.
You may find a solution to a similar problem here, which inspects the registered services in order to create the model.
It is important to note that the snippets below provide slightly different functionality which, hopefully, satisfies your particular needs. The code below expects models with ctor injections. Of course, these models have the usual properties you might have defined. These properties are filled in exactly as expected, so the bonus is the correct behavior when binding models with ctor injections.
public class DiModelBinder : ComplexTypeModelBinder
{
public DiModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders) : base(propertyBinders)
{
}
/// <summary>
/// Creates the model with one (or more) injected service(s).
/// </summary>
/// <param name="bindingContext"></param>
/// <returns></returns>
protected override object CreateModel(ModelBindingContext bindingContext)
{
var services = bindingContext.HttpContext.RequestServices;
var modelType = bindingContext.ModelType;
var ctors = modelType.GetConstructors();
foreach (var ctor in ctors)
{
var paramTypes = ctor.GetParameters().Select(p => p.ParameterType).ToList();
var parameters = paramTypes.Select(p => services.GetService(p)).ToArray();
if (parameters.All(p => p != null))
{
var model = ctor.Invoke(parameters);
return model;
}
}
return null;
}
}
This binder will be provided by:
public class DiModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null) { throw new ArgumentNullException(nameof(context)); }
if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
{
var propertyBinders = context.Metadata.Properties.ToDictionary(property => property, context.CreateBinder);
return new DiModelBinder(propertyBinders);
}
return null;
}
}
Here's how the binder would be registered:
services.AddMvc().AddMvcOptions(options =>
{
// replace ComplexTypeModelBinderProvider with its descendent - IoCModelBinderProvider
var provider = options.ModelBinderProviders.FirstOrDefault(x => x.GetType() == typeof(ComplexTypeModelBinderProvider));
var binderIndex = options.ModelBinderProviders.IndexOf(provider);
options.ModelBinderProviders.Remove(provider);
options.ModelBinderProviders.Insert(binderIndex, new DiModelBinderProvider());
});
I'm not quite sure if the new binder must be registered exactly at the same index, you can experiment with this.
And, at the end, this is how you can use it:
public class MyModel
{
private readonly IMyRepository repo;
public MyModel(IMyRepository repo)
{
this.repo = repo;
}
... do whatever you want with your repo
public string AProperty { get; set; }
... other properties here
}
Model class is created by the binder which supplies the (already registered) service, and the rest of the model binders provide the property values from their usual sources.
HTH
Is there another way than constructor injection to inject dependencies, and how?
The answer is "no", this cannot be done with "dependency injection". But, "yes" you can use the "service locator pattern" to achieve your end-goal.
You can use the code below to resolve a dependency without the use of constructor injection or the FromServices attribute. Additionally you can new up an instance of the class as you see fit and it will still work -- assuming that you have added the dependency in the Startup.cs.
public class MyRepository : IMyRepository
{
public IMyDependency { get; } =
CallContextServiceLocator.Locator
.ServiceProvider
.GetRequiredService<IMyDependency>();
}
The CallContextServiceLocator.Locator.ServiceProvider is the global service provider, where everything lives. It is not really advised to use this. But if you have no other choice you can. It would be recommended to instead use DI all the way and never manually instantiate an object, i.e.; avoid new.
I'm simply adding some supplemental information here to the answers provided that can help.
IServiceProvider was provided in the accepted answer, but not the important IServiceProvider.CreateScope() method. You can use it to create scopes as necessary that you added through ConfigureServices.
I'm not sure if IServiceProvider is actually a Service Locator pattern behind the scenes or not, but it's how you create scopes as far as I know. At least in the case if it is a Service Locator pattern, it's the official one for today in .NET, and so it's not compounded by the problems of writing your own Service Locator, which I also agree is anti-pattern.
Example, Startup.cs/ConfigureServices and Configure:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SomeDbContext>(options =>
{
options.UseSqlServer(Configuration.GetSection("Databases").GetSection("SomeDb")["ConnectionString"]);
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}, ServiceLifetime.Scoped);
services.AddMvcCore().AddNewtonsoftJson();
services.AddControllersWithViews();
}
public async void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider provider)
{
...
IServiceScope scope = provider.CreateScope();
SomeDbContext context = scope.ServiceProvider.GetRequiredService<SomeDbContext>();
SomeModelProxyClass example = new SomeModelProxyClass(context);
await example.BuildDefaults(
Configuration.GetSection("ProfileDefaults").GetSection("Something"),
Configuration.GetSection("ProfileDefaults").GetSection("SomethingSomething"));
scope.Dispose();
}
The above is for doing some default interactions on Startup, maybe if you need to build some default records in your database on a first usage, just as an example.
Ok so let's get to your repository and dependency though, will they work?
Yep!
Here's a test in my own CRUD project, I made a simple minimalist implementation of your IMyDependency and IMyRepository like so, then added them scoped as you did to Startup/ConfigureServices:
public interface IMyRepository
{
string WriteMessage(string input);
}
public interface IMyDependency
{
string GetTimeStamp();
}
public class MyDependency : IMyDependency
{
public MyDependency()
{
}
public string GetTimeStamp()
{
return DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString();
}
}
public class MyRepository : IMyRepository
{
private readonly IMyDependency _myDependency;
public MyRepository(IMyDependency myDependency)
{
_myDependency = myDependency;
}
public string WriteMessage(string input)
{
return input + " - " + _myDependency.GetTimeStamp();
}
}
Here ContextCRUD is a Model class from my own project not derived from Scaffold-DbContext tooling like my other database classes, it's a container of logic from those scaffold Model classes, and so I put it in the namespace Models.ProxyModels to hold its own business logic for doing CRUD operations so that the Controllers are not gummed up with logic that should be in the Model:
public ContextCRUD(DbContext context, IServiceProvider provider)
{
Context = context;
Provider = provider;
var scope = provider.CreateScope();
var dep1 = scope.ServiceProvider.GetService<IMyRepository>();
string msg = dep1.WriteMessage("Current Time:");
scope.Dispose();
}
Debugging I get back the expected results in msg, so it all checks out.
The calling code from the Controller for reference, just so you can see how IServiceProvider is passed from upstream by constructor injection in the Controller:
[Route("api/[controller]")]
public class GenericController<T> : Controller where T: DbContext
{
T Context { get; set; }
ContextCRUD CRUD { get; set; }
IConfiguration Configuration { get; set; }
public GenericController(T context, IConfiguration configuration, IServiceProvider provider)
{
Context = context;
CRUD = new ContextCRUD(context, provider);
Configuration = configuration;
}
...
You can do it, check out [InjectionMethod] and container.BuildUp(instance);
Example:
Typical DI constructor (NOT NEEDED IF YOU USE InjectionMethod) public
ClassConstructor(DeviceHead pDeviceHead) {
this.DeviceHead = pDeviceHead; }
This attribute causes this method to be called to setup DI.
[InjectionMethod] public void Initialize(DeviceHead pDeviceHead) {
this.DeviceHead = pDeviceHead; }

Categories