2014-02-05 109 views
2

請原諒真實但n00b級別的查詢。我正在做一個新項目並開始在IoC方面進行烘焙。這是我第一次負責構建框架的工作,所以我正在用IoC來削減我的牙齒。我正在使用Ninject的熱情推薦。涼。但是當我坐下來創建我的第一個類,它將依賴於構造函數注入,它觸發我 - 我仍然需要在構造函數中使用所有這些相當自定義的/第三方接口。那麼,如果我的類都在構造函數中使用log4net ILog實例,那麼它是如何與log4net耦合的呢?我仍然需要在每個要記錄任何內容的文件中使用log4net的聲明。IoC和綁定到接口

我以爲是你的衆多類的抽象和去耦合,並將所有的依賴關係推送到一個類中。在我看來,每一個想要記錄任何東西的類都仍然相當依賴於log4net,而將log4net更改爲另一個記錄器也是非常單調乏味的。這是一場勝利?

我確定我錯過了一些東西,所以幫助我?我是否打算在任何地方創建我自己的接口,以便實現真正的解耦,然後爲實現或其他東西添加適配器?只有這樣,我們纔會將所有依賴關係推到一個區域。

+1

相關:https://stackoverflow.com/questions/5646820/logger-wrapper-best-practice – Steven

+0

考慮將您的橫切關注點(日誌記錄)移到一個裝飾器類中,然後您將它註冊到Ninject。併爲您的第三方依賴使用代理類。 –

+0

是的,那個討論就是我期待的事情。對不起,它沒有出現在我的搜索。 – user2403744

回答

1

如果您使用IOC,則將接口注入到類中,而不是實現,這樣就可以了。爲了解決您的特定問題,請嘗試查看通用日誌記錄框架(http://netcommon.sourceforge.net/),該日誌框架本身是log4net或許多其他日誌記錄框架的封裝器。

這使您與常見的日誌記錄框架相結合,但它被非常廣泛地使用,穩定並且抽象了日誌記錄的具體內容,而無需您自己執行任何操作。

當我在過去使用過這個功能時,我使用後期構建腳本將log4net程序集帶入輸出目錄,因此綁定僅在運行時發生。就測試而言,就您的代碼而言,您正在通過所提供的公共接口與常用的日誌記錄框架進行交流。

+0

對,這就是想法,並且解決了特定的日誌記錄問題。但這是一個更普遍的問題。伐木只是一個例子。就我自己的容器而言,接口本身綁定到特定的庫的情況下,我不會比在構造函數中依賴這些接口的類中受到的束縛。一般案例本身並沒有感覺到對我有用。 – user2403744

+0

嗯,你是對的 - 你可以編寫自己的界面和你自己的包裝類,我的意思是他們必須來自某個地方嗎?我所建議的是尋找已經擁有所有代碼的可重用接口/包裝器。你仍然沒有綁定到你的注入服務的任何真正可用的實現,這意味着他們可以很容易地在以後換出。這真的取決於你想要使用的庫,以及你想採用IOC的程度。恕我直言,你越走越遠 - 你的代碼將變得越強大。它有很多工作,所以如果其他人已經做到了...... :) – Jay

+0

哦,也意味着你也可以通過配置註冊依賴關係。我使用unity而不是ninject,但原理是一樣的 - 你可以通過配置你的IOC容器來解耦你自己的接口/包裝,通過一個鬆散的文件,比如app.config或者一個特定的配置文件(IOC實現依賴於課程) 。 – Jay

0

我知道你在說什麼!你將做出一種通用化來減少代碼重複(我在跳)。就像你使用.net框架一樣,我不得不說默認情況下它不支持面向方面的編程,讓你在各種情況下表現不同。例如看看這段代碼:

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; 
     } 

我在每個服務種類我的應用程序的注入IBlogRepository,IUnitOfWrork和ILogger(log4net的)。而不是說我在每個捕獲聲明中都有類似的迴應和通用信息。一旦我想進行一種泛化,而不是重新實現每個服務類中的類似代碼,但是在這種情況下進行泛化將會更具成本效益和困難。雖然它是如此重要的是不要重複在某些情況下的代碼,例如我有這個BaseController並從中獲得我所有的控制器來自:

public class BaseController : Controller 
    { 
     private readonly ICookieStorageService _cookieStorageService; 
     private readonly ILanguageService _languageService; 

     public BaseController(ICookieStorageService cookieStorageService,ILanguageService languageService) 
     { 
      _cookieStorageService = cookieStorageService; 
      _languageService = languageService; 
     } 
    } 

所以我不需要在我的控制器創建cookieStorageService和languageService每一次,因爲我已經實施了一次。