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());
}
}
Related
I am kind of new to Unity and DI terminology, hence trying to understand how does it work. I have following code which implements DI using Unity container.
public class DashboardService: IDashboardService
{
private readonly IRepository<USERROLE> repoUserRole;
private readonly IRepository<INSTITUTION> repoInstitution;
public DashboardService(
IRepository<USERROLE> repoUserRole, IRepository<INSTITUTION> repoInstitution)
{
this.repoUserRole = repoUserRole;
this.repoInstitution = repoInstitution;
}
public List<USERROLE> GET(List<string> Id)
{
// Use repoUserRole object to get data from database
}
}
This service is being called by the controller:
public class DashboardController : ApiController
{
private readonly IDashboardService dashboardService;
public DashboardController(IDashboardService dashboardService)
{
this.dashboardService = dashboardService;
this.mapper = mapper;
}
//Action method which uses dashboardService object
}
Here is the Unity configuration:
var container = new UnityContainer();
container.RegisterType(typeof(IDashboardService), typeof(DashboardService))
.RegisterType(typeof(IRepository<>), typeof(Repository<>));
return container;
Questions:
As of now, my code works fine, but if I comment out the DashboardService constructor, I am getting the null repository objects.
I am resolving the dependencies in Unity for repository interfaces, so why I am getting null there?
Is there any way to pass the repository dependancy without using the constructor pattern?
if I comment out the DashboardService constructor, I am getting the null repository objects.
When you don't add a constructor to a class, C# will generate a public parameterless constructor for you during compilation. This causes Unity to call that 'invisible' parameterless constructor, and that's why none of your private fields are initialized.
To prevent these kinds of accidental programming errors, always make sure you enable "treat all warnings as errors" in your project's properties build tab. This will make sure the compiler stops compiling because it detects these uninitialized fields.
Is there any way to pass the repository dependancy without using the constructor pattern?
Yes there is, but every other method you could use leads to either a code smell or an anti-pattern. Constructor injection is in almost all cases the best solution.
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.
(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.
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.
I have a WCF service which calls the business component which calls the repository and I have got it end to end working using Castle Windsor using it's WCF Facility.
The WCF Facility registration and rest of the component registration happens in the Global.asax file like this.
public class Global : System.Web.HttpApplication
{
public IWindsorContainer SystemContainer;
protected void Application_Start(object sender, EventArgs e)
{
RegisterDependencies();
}
private void RegisterDependencies()
{
SystemContainer = new WindsorContainer();
SystemContainer.AddFacility<WcfFacility>().Register(
Component.For<IBookingRepository>().ImplementedBy<BookingRepository>(),
Component.For<IBookingBll>().ImplementedBy<BookingBll>(),
Component.For<IBookingService>().ImplementedBy<BookingService>(),
Component.For<ILogger>().ImplementedBy<Logger>()
);
}
}
All is well but now I need to refer this container in one of my component so that I can resolve other components like this.
public class BookingBll : IBookingBll
{
private IBookingRepository _repository;
private ILogger _logger;
public BookingBll(IBookingRepository repository)
{
_repository = repository;
_logger = SystemContainer.Resolve<ILogger>(); // This will not
//compile as we can't access a Global class property.
}
public void Add(Booking booking)
{
//Some implementation;
_logger.Write();
}
}
Moreoever I want this container to be available globally and don't want to run registration over and over again, So should I look into shuving this container in HttpRuntime.Cache so it is available and any component can simple get it from Cache and resolve what ever interface they want to.
Pardon my ignorance as I am new to WCF and as well Castle Windsor and the whole architecture has been shuved down my throat with a steep deadline :-(
How about doing it this way?
http://weblogs.asp.net/cibrax/archive/2007/12/13/wcf-dependency-injection-behavior.aspx
Approach is about implementing an Iinstanceprovider
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.iinstanceprovider.aspx
You can have a dependency on IKernel, it's automatically provided by Windsor.
public BookingBll(IKernel kernel, IBookingRepository repository) {}
If you really, really need IWindsorContainer you can register it in the container , self-registration if you wish :-)
SystemContainer.Register(Component.For<IWindsorContainer>.Instance(SystemContainer));
Then your ctor will become:
public BookingBll(IWindsorContainer container, IBookingRepository repository) {}
It's generally frowned upon to take a dependency on the container/kernel, better to inject the components you need as it will make your dependencies much clearer and your code testable. Taking a container dependency is like making Global.SystemContainer 'public static' and reference it from everywhere in your app.
In your example, the ILogger (if it's Castle.Core.ILogger) can be injected by the LoggingFacility, no need to resolve it yourself.