Reputation: 539
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.
Upvotes: 2
Views: 518
Reputation: 834
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.
Upvotes: 0
Reputation: 10108
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.
Upvotes: 1