Create an instance of class with and without injection with Unity - c#

I have an API controller, in the constructor an instance of EmployeeService is instantiated with Unity.
I'd like inject the value of myTest in the constructor of EmployeeService,
that's means an instance of Repository<Employee> will be created and the content of _myString will "TestString"
If it's possible how set the container ?
Thanks,
[RoutePrefix("api/employee")]
public class EmployeeController : ApiController
{
string myTest = "TestString";
readonly IEmployeeService _employeeService;
public EmployeeController(IEmployeeService employeeService)
{
_employeeService = employeeService;
}
}
public class EmployeeService : ServiceBase, IEmployeeService
{
private readonly IRepository<Employee> _repoEmployee;
private readonly string _myString;
public EmployeeService(IRepository<Employee> repoEmployee, string myString)
{
_repoEmployee = repoEmployee;
_myString = myString
}
}
container
.RegisterType<IRepository<Employee>, Repository<Employee>>()
.RegisterType<IEmployeeService, EmployeeService>());
My Solution :
.RegisterType<IEmployeeService, EmployeeService>(
new InjectionConstructor(
typeof(IRepository<Employee>),
"MySetting"));

To use in the service class some parameters (keys) coming from the
web.config. These parameters are read in the controller and send to
the service class
The controller should not be concerned with reading from the configuration file. In doing so, it violates the Single Responsibility Principle. This causes maintainability issues; issues that you are already experiencing, since your design causes you trouble with testing and configuring your DI library.
Since these are configuration values, they will not change during the lifetime of the application (changing the config file will cause the application to restart). Because of this, there is no reason for the controller to read them (over and over again). Instead, you can read them once during startup and inject them into the class that needs that configuration value.
In case there are multiple classes that need that configuration value, you changes are high that you are missing an abstraction. For instance, instead of injecting a connection string into many classes, consider creating an ConnectionFactory that hides the connection string from those classes and allows creating a SqlConnection on request.
But in your case, I imagine doing something like this:
TimeSpan timeOut = TimeSpan.FromSeconds(Int32.Parse(
ConfigurationManager.AppSettings["timeOut"]));
container.RegisterType<IRepository<Employee>, Repository<Employee>>();
container.RegisterType<IEmployeeService, EmployeeService>());
container.Register<IEmployeeService>(new InjectionFactory(c =>
new EmployeeService(
c.Resolve<IRepository<Employee>>(),
timeOut)));
Reading configuration values at start up has the following advantages:
It prevents your application code from depending on the configuration system itself. This makes your code more reusable, testable and maintainable.
It allows the application to fail fast at start up in case it is configured incorrectly.
It allows you to verify the correctness of your DI configuration in a test suite, without having to have the exact same configuration file in your unit test project.

Related

What is the recommended method of loading data once to user everywhere around the app?

As almost every project has some predefined setting values which are to be used throughout the application, what is the recommended way of loading them once and then using everywhere?
For example, I did a project where I had some settings stored in the database which were accessed throughout the application. Rather than querying them each and every time, I was loading everything into a static class and then would use that throughout the application. What other approach do you use?
If you have a class that retrieves your settings from the database:
public class SqlSettingsProvider : ISettingsProvider
{
private readonly string _connectionString;
public SqlSettingsProvider(string connectionString)
{
_connectionString = connectionString;
}
public Settings GetSettings()
{
// load the settings from SQL
}
}
You can register that class with your ServiceCollection:
var connectionString = "xyz"; // load this from config;
services.AddSingleton<SqlSettingsProvider>(provider =>
new SqlSettingsProvider(connectionString));
(You could have an interface like ISettingsProvider, but in this example it's not needed, because you're going to inject Settings, not the settings provider.)
Then, configure your service collection to resolve Settings by resolving SqlSettingsProvider and using it to retrieve an instance of Settings.
services.AddSingleton<Settings>(provider =>
provider.GetService<SqlSettingsProvider>().GetSettings());
Now wherever you need Settings you just inject them:
public class SomeControllerOrOtherClass
{
private readonly Settings _settings;
public SomeControllerOrOtherClass(Settings settings)
{
_settings = settings;
}
}
Now your classes can just depend on Settings and not care where it comes from. The service collection will only create it once and will then return the same instance each time, meaning it only gets looked up once from the database.
There could be some long-term benefit to injecting an interface like ISettingsProvider instead. That gives you a little bit more flexibility. For example, instead of storing the Settings for the lifetime of the application it could cache them for specified duration, or it could behave differently in some other way.

Dependency injection using options pattern

I am building an application which uses dependency injection following the options pattern design. I have a custom ORM class named DataManager. When I create an instance of DataManager I inject the connection string into the class as below.
public class DataManager : CommonDataManager {
private readonly ConnectionStrings _connectionStrings;
public DataManager(IOptions<ConnectionStrings> options) {
this._connectionStrings = options.Value;
}
When creating the DataManager object which parameter should I use? What should the initialisation code look like?
DataManager dm = new DataManager(?);
DI integration means that the DI engine is going to be responsible for object creation. So instead of directly initializing your class, you should rather do the following. Register also your DataManager with DI, so you can later instantiate it from serviceCollection:
In your ConfigureServices method add the following:
services.AddTransient<DataManager>();
Note, that you should decide the lifespan of your instance (I've chosen Transient here, but it's up to you - Singletone, Scoped, ...).
And then when you need to instantiate it, call as follows:
serviceProvider.GetRequiredService<DataManager>();
If, however, you want to go with your approach and want to instantiate the DataManager yourself, you should get the parameter from IoC container as follows:
DataManager dm = new DataManager(sp.GetRequiredService<IOptions<ConnectionStrings>>());
Note: that in both cases I assume that you've already registered the options with the DI in your Startup.ConfigureServices method.

Dependency injection resolving by name

How can I inject different implementation of object for a specific class?
For example, in Unity, I can define two implementations of IRepository
container.RegisterType<IRepository, TestSuiteRepositor("TestSuiteRepository");
container.RegisterType<IRepository, BaseRepository>();
and call the needed implementation
public BaselineManager([Dependency("TestSuiteRepository")]IRepository repository)
As #Tseng pointed, there is no built-in solution for named binding. However using factory method may be helpful for your case. Example should be something like below:
Create a repository resolver:
public interface IRepositoryResolver
{
IRepository GetRepositoryByName(string name);
}
public class RepositoryResolver : IRepositoryResolver
{
private readonly IServiceProvider _serviceProvider;
public RepositoryResolver(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IRepository GetRepositoryByName(string name)
{
if(name == "TestSuiteRepository")
return _serviceProvider.GetService<TestSuiteRepositor>();
//... other condition
else
return _serviceProvider.GetService<BaseRepositor>();
}
}
Register needed services in ConfigureServices.cs
services.AddSingleton<IRepositoryResolver, RepositoryResolver>();
services.AddTransient<TestSuiteRepository>();
services.AddTransient<BaseRepository>();
Finally use it in any class:
public class BaselineManager
{
private readonly IRepository _repository;
public BaselineManager(IRepositoryResolver repositoryResolver)
{
_repository = repositoryResolver.GetRepositoryByName("TestSuiteRepository");
}
}
In addition to #adem-caglin answer I'd like to post here some reusable code I've created for name-based registrations.
UPDATE Now it's available as nuget package.
In order to register your services you'll need to add following code to your Startup class:
services.AddTransient<ServiceA>();
services.AddTransient<ServiceB>();
services.AddTransient<ServiceC>();
services.AddByName<IService>()
.Add<ServiceA>("key1")
.Add<ServiceB>("key2")
.Add<ServiceC>("key3")
.Build();
Then you can use it via IServiceByNameFactory interface:
public AccountController(IServiceByNameFactory<IService> factory) {
_service = factory.GetByName("key2");
}
Or you can use factory registration to keep the client code clean (which I prefer)
_container.AddScoped<AccountController>(s => new AccountController(s.GetByName<IService>("key2")));
Full code of the extension is in github.
You can't with the built-in ASP.NET Core IoC container.
This is by design. The built-in container is intentionally kept simple and easily extensible, so you can plug third-party containers in if you need more features.
You have to use a third-party container to do this, like Autofac (see docs).
public BaselineManager([WithKey("TestSuiteRepository")]IRepository repository)
After having read the official documentation for dependency injection, I don't think you can do it in this way.
But the question I have is: do you need these two implementations at the same time? Because if you don't, you can create multiple environments through environment variables and have specific functionality in the Startup class based on the current environment, or even create multiple Startup{EnvironmentName} classes.
When an ASP.NET Core application starts, the Startup class is used to bootstrap the application, load its configuration settings, etc. (learn more about ASP.NET startup). However, if a class exists named Startup{EnvironmentName} (for example StartupDevelopment), and the ASPNETCORE_ENVIRONMENT environment variable matches that name, then that Startup class is used instead. Thus, you could configure Startup for development, but have a separate StartupProduction that would be used when the app is run in production. Or vice versa.
I also wrote an article about injecting dependencies from a JSON file so you don't have to recompile the entire application every time you want to switch between implementations. Basically, you keep a JSON array with services like this:
"services": [
{
"serviceType": "ITest",
"implementationType": "Test",
"lifetime": "Transient"
}
]
Then you can modify the desired implementation in this file and not have to recompile or change environment variables.
Hope this helps!
First up, this is probably still a bad idea. What you're trying to achieve is a separation between how the dependencies are used and how they are defined. But you want to work with the dependency injection framework, instead of against it. Avoiding the poor discover-ability of the service locator anti-pattern. Why not use generics in a similar way to ILogger<T> / IOptions<T>?
public BaselineManager(RepositoryMapping<BaselineManager> repository){
_repository = repository.Repository;
}
public class RepositoryMapping<T>{
private IServiceProvider _provider;
private Type _implementationType;
public RepositoryMapping(IServiceProvider provider, Type implementationType){
_provider = provider;
_implementationType = implementationType;
}
public IRepository Repository => (IRepository)_provider.GetService(_implementationType);
}
public static IServiceCollection MapRepository<T,R>(this IServiceCollection services) where R : IRepository =>
services.AddTransient(p => new RepositoryMapping<T>(p, typeof(R)));
services.AddScoped<BaselineManager>();
services.MapRepository<BaselineManager, BaseRepository>();
Since .net core 3, a validation error should be raised if you have failed to define a mapping.

Logging as a decorator vs. Dependency Injection - what if I need to log inside the class?

(I originally asked this question in this comment, but Mark Seemann asked me to create a new question instead.)
I'm starting a new app (.NET Core, if that matters), and right now I'm trying to decide how exactly to do logging.
The general consensus seems to be that logging is a cross-cutting concern, so the logger shouldn't be injected directly into the class that is supposed to log.
Often, there's an example like the following class how not to do it:
public class BadExample : IExample
{
private readonly ILogger logger;
public BadExample(ILogger logger)
{
this.logger = logger;
}
public void DoStuff()
{
try
{
// do the important stuff here
}
catch (Exception e)
{
this.logger.Error(e.ToString());
}
}
}
Instead, the class with the business logic shouldn't know about the logger (SRP) and there should be a separate class which does the logging:
public class BetterExample : IExample
{
public void DoStuff()
{
// do the important stuff here
}
}
public class LoggingBetterExample : IExample
{
private readonly IExample betterExample;
private readonly ILogger logger;
public LoggingBetterExample(IExample betterExample, ILogger logger)
{
this.betterExample = betterExample;
this.logger = logger;
}
public void DoStuff()
{
try
{
this.betterExample.DoStuff();
}
catch (Exception e)
{
this.logger.Error(e.ToString());
}
}
}
Whenever an IExample is needed, the DI container returns an instance of LoggingBetterExample, which uses BetterExample (which contains the actual business logic) under the hood.
Some sources for this approach:
Blog posts by Mark Seemann:
Instrumentation with Decorators and Interceptors
Dependency Injection is Loose Coupling
Blog post and SO answer by Steven:
Meanwhile... on the command side of my architecture
Windsor - pulling Transient objects from the container
My question:
Obviously, the LoggingBetterExample approach only works as long as the logging can be done outside the actual class.
(like in the example above: catch any exceptions thrown by BetterExample from outside)
My problem is that I'd like to log other things inside the actual class.
Mark Seemann suspected here that if someone needs to do this, maybe the method in question is doing too much.
As I said before, I'm in the planning phase for a new application, so I don't have much code to show, but the use case I'm thinking right now is something like this:
My app will have a config file with some optional values.
The user may decide to omit the optional values, but it's an important decision to do this.
So I'd like to log a warning when some of the optional values are missing, just in case it happened by error.
(omitting the values is perfectly fine though, so I can't just throw an exception and stop)
This means that I will have a class which reads config values and needs to do something like this (pseudocode):
var config = ReadConfigValues("path/to/config.file");
if (config.OptionalValue == null)
{
logger.Warn("Optional value not set!");
}
No matter if ReadConfigValues is in this class or a different one, I don't think this class would violate the SRP.
When I'm not able to log outside the actual class by using a decorator, is there a better solution than to inject the logger?
I know I could read the config file in the inner class, but check the values (and log the warning) in the decorator. But IMO checking the value is business logic and not infrastructure, so to me it belongs in the same class where the config file is read.
checking the value is business logic and not intfastructure, so to me it belongs in the same class where the config file is read.
Obviously, I don't know your domain well enough to dispute the truth of that assertion, but that logging is part of the domain model sounds strange to me. Anyway, for the sake of argument, let's assume that this is the case.
What ought not to be the case, though, is that reading a configuration file is domain logic. While reading and manipulating the data from a file could easily be domain logic, reading a file is I/O.
The most common approach to Inversion of Control in application architecture is to employ the Ports & Adapters architecture. The entire point of such an architecture is to decouple the domain model from I/O, and other sources of non-determinism. The poster example is to show how to decouple the domain model from its database access, but file access falls squarely in that category as well.
What this ought to imply in this particular case is that you're going to need some IConfigurationReader interface anyway. This means that you can apply a Decorator:
public class ValidatingConfigurationReader : IConfigurationReader
{
private readonly IConfigurationReader reader;
private readonly ILogger logger;
public ValidatingConfigurationReader(IConfigurationReader reader, ILogger logger)
{
this.reader = reader;
this.logger = logger;
}
public MyConfiguration ReadConfigValues(string filePath)
{
var config = this.reader.ReadConfigValues(filePath);
if (config.OptionalValue == null)
{
this.logger.Warn("Optional value not set!");
}
return config;
}
}
This ValidatingConfigurationReader class can be implemented in the domain model, even if the underlying, file-reading IConfigurationReader implementation belongs in some I/O layer.
Don't take SRP so seriously, otherwise you'll end up with functional programming. If you afraid of getting your class cluttered by putting log statements inside it, then you have two options. The first one you already mentioned which is using a Decorator class but you can't access/log the private stuff. The second option is using partial classes and putting the logging statements in a separate class.

Is this a good example of the "Bastard injection anti-pattern"?

I see lead developers writing code like this and upon reading Mark Seemann's book "Dependency Injection in .NET" I'm wondering if the specific "new" is "foreign", thus "Bastard Injection"??
public class SessionInitServiceManager
{
protected readonly ICESTraceManager _traceManager;
protected readonly ILogger _logger;
protected readonly IAggregateCalls _aggregator;
protected readonly IMultiCoreRepository _repository;
public SessionInitServiceManager(ICESTraceManager traceManager,
ILogger logger,
IAggregateCalls aggregator,
IMultiCoreRepository repository)
{
_traceManager = traceManager;
_logger = logger;
_aggregator = aggregator;
_repository = repository;
}
public SessionInitServiceManager() : this(new CESTraceManager(),
new Logger("BusinessServices.authenticateUser"),
new Aggregator(),
new RepositoryFactory().BuildMultiCoreRepository()) { }
This for sure looks like a classic example of Bastard Injection. The reason why is because you have what appears as four Foreign Defaults. Foreign Default refers to a default value in which the type comes from a different module/project/DLL. I would propyl include namespace into that definition, because name spaces can signify boundaries in which at a future point you make breakout into its own module. This is more of being mindful about that when you decide to use a local default (Would I split this into its own module in the future?).
The way this wouldn’t be Bastard Injection would be that all these classes live within the same module. The thing that makes this so bad is because you drag the dependencies along, and now your class is tightly coupled to these classes. If I choose to use my own version of logging I have to take along the DLL for logging and so on, even though I don’t use, negating the benefits of modular application design.
I happened to have borrowed that book, dependency injection in .NET, from a friend. I see what you are saying. I do believe that this is "bastard injection". It is a brutal term, but I suppose fitting after all ColdFusion (cough) has a "CFABORT" tag as part of the language.
Also, I noticed a good article, blog post How not to do dependency injection - the static or singleton container.
Basically, before we begin, let's get something out of the way:
Dependency Injection != Using an IoC container"
Here is the kicker, "This is the birth of the static container. Instead of changing the constructor of the controller to take in the dependency, we are just changing the line where the service is instantiated to resolve it using the container instead."
public class HomeController
{
private readonly IExampleService _service;
public HomeController()
{
_service = Container.Instance.Resolve<IExampleService>();
}
public ActionResult Index()
{
return View(_service.GetSomething());
}
}

Categories