Forgive a genuine but n00b level query, please. I'm doing a new project and starting to bake in the IoC aspect of it. It's the first I've worked on where I was in charge of building up the framework so I'm cutting my teeth with IoC somewhat. I'm taking a hearty recommendation to use Ninject. Cool.
But as I sit down to create my first class that will rely on constructor injection, it strikes me - I still need to use all of these quite custom/3rd party interfaces in the constructors. So How is it that my code is less coupled to log4net if my classes all take a log4net ILog instance in their constructor? I still need a using statement for log4net in each file that wants to log anything.
I thought that was the point - abstraction and de-coupling of your multitudes of classes, and pushing all of the dependencies into one class. It seems to me that every class that wants to log anything is still quite bound to log4net, and to change log4net out for another logger would be tedious all the same. how is this a win?
I'm sure I'm missing something, so help me out? Am I meant to create my own interfaces everywhere I wanted to be truly decoupled and then add adapters for the implementations or something? Only then would it seem to be we've pushed all the dependencies to one area.
If you use IOC, you inject the interfaces into your class, not the implementation, so that is ok. To get around your specific problem, try looking at the common logging framework (http://netcommon.sourceforge.net/) which itself is a wrapper for log4net or a multitude of other logging frameworks.
This couples you to the common logging framework, but it is very widely used, stable and abstracts the specific of logging without you having to do any of that yourself.
When I have used this in the past, I use a post build script to bring the log4net assemblies into the output directory, so the binding happens at runtime only. For testing purposes and as far as your code is concerned, you are talking to the common logging framework via the public interface provided.
I know what are you talking about! you are going to make a kind of generalization to reduce code duplication(I'm hopping). as you are using .net framework, I have to say that it does not support for aspect oriented programming by default to let you behave different in every situation. for example take a look at this piece of code:
public class BlogService : IBlogService
{
private readonly IBlogRepository _blogRepository;
private readonly IUnitOfWork _unitOfWork;
private readonly ILogger _logger;
public BlogService(
IBlogRepository blogRepository,
IUnitOfWork unitOfWork,
ILogger logger)
{
_blogRepository = blogRepository;
_unitOfWork = unitOfWork;
_logger = logger;
}
public GetAllBlogPostResponse GetAllBlogPost(GetAllBlogPostRequest request)
{
var response = new GetAllBlogPostResponse();
try
{
var blogPosts = _blogRepository.GetAll();
if (blogPosts != null)
{
response.BlogPostViewModel = blogPosts.ConvertToPostListViewModel();
response.Success = true;
response.MessageType = MessageType.Success;
response.Message = ServiceMessages.GeneralServiceSuccessMessageOnRetrieveInformation;
_logger.Log(string.Format(response.Message));
}
else
{
response.MessageType = MessageType.Info;
response.Message = ServiceMessages.GeneralServiceAlarmMessageOnRetrieveInformation;
_logger.Log(string.Format(response.Message));
}
}
catch (Exception exception)
{
response.Success = false;
response.Message = ServiceMessages.GeneralServiceAlarmMessageOnRetrieveInformation;
_logger.Log(string.Format(response.Message));
_logger.Log(exception.Message);
}
return response;
}
I have injected IBlogRepository, IUnitOfWrork and ILogger(Log4net) in every service class of my application. rather than that I have similar response and generic message in every catch statement. once I wanted to make a kinds of generalization and not to re-implement the similar code in every service class but you making generalization in such a condition will be more cost effective and difficult. although it's so important to not duplicate the code in some situations, for example I have this BaseController and derive all of my controller from that:
public class BaseController : Controller
{
private readonly ICookieStorageService _cookieStorageService;
private readonly ILanguageService _languageService;
public BaseController(ICookieStorageService cookieStorageService,ILanguageService languageService)
{
_cookieStorageService = cookieStorageService;
_languageService = languageService;
}
}
so I don't need to create the cookieStorageService and languageService in my controllers each time as I have implemented it in for once.
Related
I'm learning dependency injection, because I don't want my BE to look spaghety no more. I have a good understanding of Asp.Net Core and EF Core. I just never learned dependecy injection properly. I'm playing around with an idea. Let's say, that I create an EmailSenderService (and IEmailSenderService with it). I do the same for CustomLogger and WeatherRepository. Here are the implementations:
Program.cs:
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddScoped<ICustomLogger, CustomLogger>();
builder.Services.AddScoped<IEmailSenderService, EmailSenderService>();
builder.Services.AddScoped<IWeatherRepository, WeatherRepository>();
// Add swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
CustomLogger.cs
public interface ICustomLogger
{
public void Log(string logText);
}
public class CustomLogger : ICustomLogger
{
public void Log(string logText) => System.Diagnostics.Debug.WriteLine(logText);
}
EmailSenderService.cs
public interface IEmailSenderService
{
public void SendMail(string email, string text);
}
public class EmailSenderService : IEmailSenderService
{
public void SendMail(string email, string text) => System.Diagnostics.Debug.WriteLine($"TO: {email}, TEXT: {text}");
}
WeatherForecastModel.cs
public struct WeatherForecastModel
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
WeatherRepository.cs
public interface IWeatherRepository
{
public WeatherForecastModel[] GetRandomSample();
}
public class WeatherRepository : IWeatherRepository
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public WeatherForecastModel[] GetRandomSample() =>
Enumerable.Range(1, 5).Select(index => new WeatherForecastModel
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
}).ToArray();
}
WeatherForecastController.cs
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly ICustomLogger _customLogger;
private readonly IEmailSenderService _emailSenderService;
private readonly IWeatherRepository _weatherRepository;
public WeatherForecastController(ICustomLogger customLogger, IEmailSenderService emailSenderService, IWeatherRepository weatherRepository)
{
_customLogger = customLogger;
_emailSenderService = emailSenderService;
_weatherRepository = weatherRepository;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecastModel> Get()
{
_customLogger.Log("Started function GetWeatherForecast");
WeatherForecastModel[] results = _weatherRepository.GetRandomSample();
_customLogger.Log("Started sending mail.");
_emailSenderService.SendMail("some.mail#domain.com", $"Summary of the first result: {results[0].Summary}");
_customLogger.Log("Ended sending mail.");
_customLogger.Log("Ended function GetWeatherForecast");
return results;
}
}
Now, with the whole implementation, in place, I don't like it. Like visually. I do not want to see logging and email sending logic inside of my controller. This is the fundamentaly issue, I'm trying to solve with this question. I could (I implemented it for testing) inject logger inside the EmailSenderService and inside the WeatherRepository and log there, howerver, I do not like that either. I do not want to see logging inside of my logic. So, I thought about something I called LogAwareEmailSenderService. Here is impelementation:
public class LogAwareEmailSenderService : IEmailSenderService
{
private readonly ICustomLogger _customLogger;
private readonly IEmailSenderService _emailSenderService;
public LogAwareEmailSenderService(ICustomLogger customLogger, IEmailSenderService emailSenderService)
{
_customLogger = customLogger;
_emailSenderService = emailSenderService;
}
public void SendMail(string email, string text)
{
_customLogger.Log($"Started sending email to: {email}, containing text: {text}");
_emailSenderService.SendMail(email, text);
_customLogger.Log($"Done sending email to: {email}, containing text: {text}");
}
}
Basically, what I'm trying to achieve, is: Take my original EmailSenderService, then inject it into my LogAwareEmailSenderService. The idea is, that now, I should be able to inject this LogAwareEmailSenderService into my controller without the need to change my controller at all (just remove my previous logging logic), right? And If I achieve this, I can go on and continue, to make something like LogAndEmailAwareWeatherRepository, that will inject LogAwareEmailSenderService and instead of sending mail and logging function start inside of the controller. I will just call LogAndEmailAwareWeatherRepository, that will log these things, and send the email, resulting in controller only calling the important, _weatherRepository.GetRandomSample() -- This call will do the logging and sending mail, using the previously described abstractions.
However, in the first place, I am unable to inject the EmailSenderService inside the LogAwareEmailSenderService. I want them both to be scoped. I trid this approach (in my Program.cs):
builder.Services.AddScoped<IEmailSenderService, EmailSenderService>();
builder.Services.AddScoped<IEmailSenderService, LogAwareEmailSenderService>();
however I got circular dependency error:
'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: DependencyInjectionExample.Services.EmailSenderService.IEmailSenderService Lifetime: Scoped ImplementationType: DependencyInjectionExample.Services.EmailSenderService.LogAwareEmailSenderService': A circular dependency was detected for the service of type 'DependencyInjectionExample.Services.EmailSenderService.IEmailSenderService'.
DependencyInjectionExample.Services.EmailSenderService.IEmailSenderService(DependencyInjectionExample.Services.EmailSenderService.LogAwareEmailSenderService) -> DependencyInjectionExample.Services.EmailSenderService.IEmailSenderService)'
So, I got some questions:
Am I going about this right? Like, is what I described above, the normal approach to things?
Where should I put my Logging logic? When doing this, I also thought about caching things, meaning, that I would have something like CacheAwareWeatherRepository, that would only care about the caching implementation and then call the WeatherRepository to get data and return them, while caching them.
How to implement my solution?
I still don't understand some parts of dependecy injection, are there any articles/books that helped you personally understand it?
If you've got here, thank you, I know it is long, however I wanted to describe my problem, possible solutions, and questions clearly.
If you have any questions, about anything, please feel free to ask me in comments, or email me (if it's long question) to dibla.tomas#email.cz. I would really like to get to the bottom of this.
PS: This is not about implementation of bussiness logic, or anything like this, this is only for getting data, logging it, caching it and doing abstractions above data access. I implemented this, with idea that you would have one interface and then layers of abstractions. One for getting the actual data (fAb), One for logging the fact (sAb) implementing fAb, One for caching data (tAb) implementing sAb, One for logging the fact of caching (qAb) implementing tAb. And so on.
Am I going about this right? Like, is what I described above, the normal approach to things?
There's not a right/wrong, but what you're describing is an accepted pattern, called the decorator pattern. One service adds behaviors around another one while implementing the same interface.
Where should I put my Logging logic?
Depends on what you mean by "logging logic." The true logic of your logging (opening files and writing to them, e.g.) is already abstracted away behind the logger interface, as it should be.
If you like to have generic messages logged every time a public method is entered or exited, then you can do that with an aspect-oriented Fody Weaver to avoid repetitive code.
The lines of code that decide what to output as a log message, on the other hand, are mostly going to be specific to your implementation. The most useful diagnostic messages are probably going to be ones that need to know contextual information about your specific implementation, and that code needs to be embedded within the implementation code itself. The fact that you "visually don't want to see" calls to the logging service in your controller code is something you should get over. Diagnostic logging is a cross-cutting concern: a responsibility inherent to every class regardless of what their "single responsibility" is supposed to be.
How to implement my solution?
The DI registration method can take a delegate that lets you be more specific about how the type is resolved.
builder.Services.AddScoped<EmailSenderService>(); // allow the next line to work
builder.Services.AddScoped<IEmailSenderService>(p => new LogAwareEmailSenderService(
p.GetRequiredService<ICustomLoggerService>(),
p.GetRequiredService<EmailSenderService>()));
I still don't understand some parts of dependecy injection, are there any articles/books that helped you personally understand it?
Technically not the sort of question we're supposed to be asking on StackOverflow, but I learned from Mark Seeman's Dependency Injection in .NET (affiliate link). It's kind of old now, so library-specific details are outdated, but the principles are enduring.
I thought it might be worth mentioning the Scrutor library which lets you easily specify the decoration setup. For example, you could have:
builder.Services.AddScoped<IEmailSenderService, EmailSenderService>();
builder.Services.Decorate<IEmailSenderService, LogAwareEmailSenderService>();
Edit: the Decorator pattern is a great way to honour Single Responsibility while enabling the Open/Closed principle: you're able to add new decorators to extend the capabilities of your codebase without updating the existing classes.
However, it comes with the cost of a somewhat more involved setup. The Scrutor library takes care of the decoration so that you don't need to manually code how the services are composed. If you don't have many decorators, or you don't have many levels of decoration, then that advantage might not be useful to you.
The scanning capability is not related to the decorator setup: it's simply another capability that allows one to add classes to the service collection without manually the classes (sort of auto-discovery). You can do this via reflection.
Here's an example of the decorator setup if you also had caching:
builder.Services.AddScoped<IWeatherRepository, WeatherRepository>();
builder.Services.Decorate<IWeatherRepository, DiagnosticsWeatherRepositoryDecorator>();
builder.Services.Decorate<IWeatherRepository, CachedWeatherRepositoryDecorator>();
You could do this manually:
builder.Services.AddScoped<WeatherRepository>();
builder.Services.AddScoped(provider => new DiagnosticsWeatherRepositoryDecorator(provider.GetRequiredService<WeatherRepository>()));
builder.Services.AddScoped<IWeatherRepository>(provider => new CachedWeatherRepositoryDecorator(provider.GetRequiredService<DiagnosticsWeatherRepositoryDecorator>)));
It becomes a bit more involved if the constructors take other parameters. It's completely possible, but really verbose.
I thought I'd also share some advice regarding your 5th question; my experience of dependency injection frameworks is that:
The frameworks are simply a key-value map; if a class needs interface A, then create class B.
Sometimes it's just a key; that happens when you only need to let the framework know that class C exists.
Whenever a class needs to be created, the map of all classes and all interface/class to class mappings are consulted, and whatever the map lists is created.
It seems like you're aware, but these frameworks also manage the lifetime of the objects it creates. For example, a scoped lifetime is linked to the duration of the http request. This means that an IDisposible object created by the framework, will be deposed once the request ends.
In your case:
builder.Services.AddScoped<IEmailSenderService, EmailSenderService>();
builder.Services.AddScoped<IEmailSenderService, LogAwareEmailSenderService>();
The second statement actually overwrites the mapping of the first statement: you can only have one key (in this case IEmailSenderService) in the collection. So when the framework tried to create LogAwareEmailSenderService it saw that LogAwareEmailSenderService needs an IEmailSenderService but the only one it knows about is LogAwareEmailSenderService.
This is why we only list the interface once when we manually tied up the decorated classes. When the Scrutor library is used, it re-maps the types allowing you to list the interface multiple times.
I've just come from a place where an API controller would have just the Services it needed injected in to it...
[ApiController]
public class SomeController : ControllerBase
{
private IFirstService firstService
private ISecondService secondService
public SomeController(IFirstService firstService, ISecondService secondService)
{
this.firstService = firstService;
this.secondService = secondService;
}
[HttpGet]
public IActionResult SomeMethod()
{
var data = firstService.GetSomething();
return OkObjectResult(data);
}
}
Now I find myself in a shop that does this...
[ApiController]
public class SomeController : ControllerBase
{
private IServiceProvider services;
public SomeController(IServiceProvider services)
{
this.services = services;
}
[HttpGet]
public IActionResult SomeMethod()
{
var service = servies.Get<IFirstService>();
if(service is null)
{
//...
}
var data = firstService.GetSomething();
return OkObjectResult(data);
}
}
Now, I can't really explain why, but this just seems wrong.
Am I just experiencing StuckInMyWaysitis or is this really the bad practice my bones tells me it is? Or, is there, in fact, a more widely accepted way of doing the "right" thing?
Injecting IServiceProvider implements the Service Locator pattern, which is generally considered to be an anti-pattern.
In your first example two services are injected. You can easily tell what the controller depends on. It's easier to tell if a class begins to depend on too many things when we see five, 10, or 20 dependencies injected. When that happens we usually refactor because the number of dependencies indicates that the class is doing too many things.
In the second example we can't tell from the injected dependency (IServiceProvider) what the class depends on. The only way to tell is to look at every use of services throughout the class and see what gets resolved from it. A class could end up depending on many other classes even though we only see one dependency in the constructor.
This also makes unit testing more difficult. In the first example we might have to create fakes or mocks for one or both services. In the second example we have to either mock IServiceProvider to return mocks or create an IServiceCollection, register the mocks with it as service implementations, and then build a ServiceProvider from it. Both make tests more complex.
Some have reasoned that API controllers are an exception, and that it's okay to have them depend on something like a service locator. (MediatR is a common example.) This is an opinion: It's not bad as long as the controller has little or no logic and is only used to route HTTP requests to some higher-level code.
If we use MediatR or some similar abstraction like ICommandHandler<TCommand> then at least we've constrained the class to submitting queries or commands to handlers. It's not as bad as injecting IServiceProvider which allows the class to resolve any registered service.
It's wrong because it means that every time you need a service you have to explicitly request it and then check the instance for null. This is unnecessary code duplication for no benefit.
It also violates the explicit dependencies principle, which Microsoft recommends you use to architect your code.
Almost certainly this was done because somebody couldn't figure out how DI works, or they forgot to register a service and couldn't be a***d to fix it properly, so they just chucked in IServiceProvider instead and that ended up working, and then they cargo-culted it everywhere. In other words, laziness and/or ignorance.
Likely you will come up against resistance when you try to fix this by using explicit dependencies. The trick is to make the person(s) advocating for this mess explain why the mess is better than following good architectural practices, particularly those from Microsoft.
When you've been programming long enough, you learn to trust your gut. If it feels bad, it almost always is.
First, Let us refactor the second code to get rid of some code smells,
[ApiController]
public class SomeController : ControllerBase
{
private IFirstService firstService
private ISecondService secondService
private IServiceProvider services;
public SomeController(IServiceProvider services)
{
this.services = services;
this.firstService= servies.Get<IFirstService>();
this.secondService= servies.Get<ISecondService>();
}
[HttpGet]
public IActionResult SomeMethod()
{
var data = firstService.GetSomething();
return OkObjectResult(data);
}
}
Why?
you automatically get rid of all the checks, and now you can do that in your constructor if needed.
If many methods needed instances all might have duplicate codes like this.
It violates SRP as the methods are doing more than they should be.
Now if we look it is closer to your First code. With one difference, Instantiating service vs Injecting service. There are a few problems with this IMO,
DI Containers are tools, they are not part of our domain. By taking IServiceProvider, we are trying our services to them. Which implies we always need some DI provider.
Secondly this also hides our dependencies, which makes integration
difficult. Constructors are like messengers that clearly tell us
what we need to keep ready beforehand, before we instantiate a
Class. If we hide this information, you may not know if certain
dependency was configured or not without running the application.
With clearly defined dependencies in constructor, we cannot skip
this part.
Also, just like we had duplicate code in our methods, now we have duplicate code in constructor of different services. Each service will be calling these Get methods. So why not do them in one place. And if you consider this and refactor, you automatically reach to your first example.
[ApiController]
public class SomeController : ControllerBase
{
private IFirstService firstService
private ISecondService secondService
public SomeController(IFirstService firstService, ISecondService secondService)
{
this.firstService = firstService;
this.secondService = secondService;
}
}
public class Startup()
{
public void Start()
{
//....
//....
var service1 = servies.Get<IFirstService>();
var service2 = servies.Get<IFirstService>();
SomeController= new Controller(service1,service2);
//or just servies.Get<SomeController>();
}
}
This is how instantiation happen if you use Containers like AutoFac.
My team is pretty big on DependencyInjection. Personally I'm a bit too far out of the loop lately to really judge the correct usage of this. But I do see more and more code like this:
public AuthenticationApi(ILogger<AuthenticationApi> logger,
HttpClient httpClient,
IJsonConverter jsonConverter,
IDtoConverter dtoConverter) : base(logger, httpClient, jsonConverter)
{
_dtoConverter = dtoConverter;
}
And then this multiplies across the code, where half of our code is just calling constructors with endless
DependencyInjection related stuff. My team told me, that's the way of .NET Core. And yes, answers like this confirm it:
ILogger and DependencyInjection in ASP.NET Core 2+
And discussions like that would be more along my gut feeling that things like logging, etc. should just be transparent and not handled in endless DependencyInjection constructor chains:
https://softwareengineering.stackexchange.com/questions/371722/criticism-and-disadvantages-of-dependency-injection
In another place (unfortunately I can't find the article anymore), I read that this constructor issues are mainly a result of badly implemented Service Factories.
Thoughts on the topic are appreciated.
Based on the discussion below, this is the baseclass and uses both the Logger and the HttpClient:
internal class ApiBase
{
private readonly ILogger _logger;
private readonly IJsonConverter _jsonConverter;
private readonly HttpClient _httpClient;
public ApiBase(ILogger logger, HttpClient httpClient, IJsonConverter jsonConverter)
{
_logger = logger;
_jsonConverter = jsonConverter;
_httpClient = httpClient;
}
protected async Task<T> GetAsync<T>(string path, HttpContent content = null)
{
_logger.LogDebug($"Sending GET request to {path}");
using (var request = new HttpRequestMessage(HttpMethod.Get, path))
{
request.Content = content;
using (var response = await _httpClient.SendAsync(request).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
_logger.LogDebug($"GET request to {path} was successful.");
var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var deserializeResponseContent = _jsonConverter.Deserialize<T>(responseContent);
return deserializeResponseContent;
}
var message = GetErrorMessage("GET", path, response);
_logger.LogError(message);
throw new HttpRequestException(message);
}
}
}
And then this multiplies across the code, where half of our code is just calling constructors with endless DependencyInjection related stuff. My team told me, that's the way of .NET Core.
Yes and no. Constructor injection of dependencies is a standard method in .NET Core to organize your dependencies. And it works great.
What is non-standard is your base class and the fact that you have those constructor chains where half your parameters aren't actually needed, but just go into the base class constructor. I will bet that this base class does not actually do anything worthwhile.
Remove the base class. See what you still need for every controller. Only inject that. These base classes and their own constructors are a great way to obfuscate what the actual dependencies are. Because now suddenly every class needs an IJsonConverter, must be pretty important. But you will have a hard time figuring out who actually makes use of the base class functionality that uses it. So of your 20 classes derived of the base, who really needs it, and who only requires it to make the compiler happy?
My advice is to remove the base class. Inject into each controller what they need, not more and not less. So you can actually see the dependencies. If you have common functionality in that base class, it can probably be a static method somewhere that gets those fields as parameters. Or maybe it can be a service of it's own that is injected where needed. But only where needed.
Following this answer I did this :
public class Log4netAdapter<T> : ILogger
{
private static readonly log4net.ILog logger = LogManager.GetLogger(typeof(T));
public void Log(LogEntry entry)
{
if(entry.LoggingEventType == LoggingEventType.Information)
logger.Info(entry.Message, entry.Exception);
else if(entry.LoggingEventType == LoggingEventType.Warning)
logger.Warn(entry.Message, entry.Exception);
else if(entry.LoggingEventType == LoggingEventType.Error)
logger.Error(entry.Message, entry.Exception);
else
logger.Fatal(entry.Message, entry.Exception);
}
}
And then on the Simple Injector :
container.RegisterConditional(
typeof(ILogger),
c => typeof(Log4netAdapter<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
This works great if I inject the ILogger on every class constructor I need. My problem is that I have some classes that I cannot use the constructor injection. For this cases I would tipically do :
var logger = SimpleInjectorInitializer.Container.GetInstance<ILogger>();
However the above method does not work, it throws an error on the simple injector class since the c.Consumer is null.
Here is one of the examples I need to resolve ILogger, this class is registered on the webapi startup class.
public class ExceptionWebApiHandlingAttribute : IExceptionFilter
{
public ExceptionWebApiHandlingAttribute()
{
}
}
Is there any alternative ?
Thanks
When working on the application boundary, it is sometimes hard or impossible to use constructor injection. Typical examples are MVC filter attributes or ASP.NET Web Form Page classes that require a default constructor.
A typical solution to these problems is to make such boundary class into a Humble Object, where all interesting logic is extracted from the boundary class into a component. The boundary class should only contain the call to the Service Locator and call one method on the resolved service. This minimizes the amount of untestable code in the application.
In all other cases, constructor injection should be preferred.
The fact however that you resolve an ILogger implies that your boundary class does too much. Instead this ILogger should be a constructor dependency of the component that you extracted from the boundary class to become a Humble Object.
Once you've done this, you won't be resolving ILogger directly anymore and this solves your problem; ILogger has become a dependency of a consumer and this ensures that Simple Injector is able to build the correct Logger<T> on your behalf.
When it comes to applying dependencies to exception filters in Web API (your particular case), a good solution is to create a proxy for your exception filters that will delegate the call to the real filter that gets resolved. This can be a bit of infrastructure and the concept is explained here.
If it is impossible to apply the above advise, for whatever reason, you can always request a Logger<T> directly from the container:
ILogger log = SimpleInjectorInitializer.Container.GetInstance<Logger<MyHumbleObject>>();
I am writing a plugin as part of a plugin architecture. The way plugins are created is via reflection and CreateInstance. Therefore the default constructor is called. This code I cannot touch and I am trying to find a sensible way to use DI without the ability to use a framework.
I believe I have 3 options:
i) Poor Man's DI (PMDI)
ii) Factory Pattern
iii) TinyIOC or similar (one cs file that handles DI)
I started looking at PMDI but then a dependency needed another dependency so I ended up with something similar to this which is ugly and could get worse:
public MyMainPluginClass() : this(new Repo(new Logger()))
{
}
public MyMainPluginClass(IRepo repo)
{
}
I then moved onto the idea of a Factory Pattern but could not find any decent demo code. I assume I would have something like this:
public static FactoryUtility
{
public static IRepo GetRepo()
{
return new Repo(GetLogger());
}
public static ILogger GetLogger()
{
return new Logger();
}
}
public MyMainPluginClass() : this(FactoryUtility.GetRepo())
{
}
public MyMainPluginClass(IRepo repo)
{
}
Is that how it would look?
I then came across TinyIOC which is one class that does all the dependency registering but I believe it requires to be setup in a Program.cs which I don't have in a class library. If someone has any experience using this could it be used like so:
public MyMainPluginClass()
{
var container = TinyIoCContainer.Current;
container.AutoRegister();
var implementation = container.Resolve<IRepo>();
MyMainPluginClass(implementation);
}
public MyMainPluginClass(IRepo repo)
{
}
Are there any alternative approaches to achieve DI without using a 3rd party library and if not which approach would choose from above?
NOTE: The code above has not been compiled and is just an idea of what I think would work. Please post corrections if they are valid approaches.
Since you're using .NET 4, you might want to consider using MEF, as it's built into the framework itself. This looks like fairly straightforward DI, which MEF handles well, as it's intended mainly for extensibility.
For details, see the Learn More page on the MEF CodePlex site.
I went with TinyIOC in the end. Unfortunately the plugin's constructor gets called several times before its actually up and running. I simply set a boolean to prevent registration being called several times and therefore it allows me to simply auto-register dependencies and off we go.
public MyMainPluginClass() : this(FactoryUtility.SetupIOC())
{
}
public MyMainPluginClass(IRepo repo)
{
}
public static class FactoryUtility
{
private static bool Initialized = false;
public static IRepo SetupIOC()
{
var container = TinyIoCContainer.Current;
if (!Initialized)
{
container.AutoRegister(new[] { Assembly.GetExecutingAssembly() });
Initialized = true;
}
var result = container.Resolve<IRepo>();
return result;
}
}
If I absolutely don't want to add a dependency to a DI container, I like to use my own TinyIOC (sorry about the name, didn't know it was taken), which for small projects gives me the same semantics as using a container, but clocks in at below 200 LOC.
If you are interested, here is the code: https://gist.github.com/ad7608e2ae10b0f04229