6

के साथ एनएलओजी आईएलओगर पंजीकरण करना क्या कोई तरीका है कि मैं संदर्भ प्राप्त कर सकता हूं ताकि मैं loggerName पुनर्प्राप्त कर सकूं और LogManager.GetCurrentClassLogger() के बजाय LogManager.GetLogger(loggerName) का उपयोग कर सकूं?सरल इंजेक्टर

मैंने देखा कि container.RegisterConditional() पर संदर्भ के लिए उपयोग है।

इसके अलावा, मैं अब SimpleLogging.NLog जैसे समाधानों से बचना चाहता हूं।

अंत में, मैं स्वीकार करने के लिए तैयार हूं कि यह सही दृष्टिकोण नहीं है। बीटीडब्ल्यू, एओपी एक विकल्प है जिसे मैंने पहले से ही खोजा है (Is it a good practice to have logger as a singleton?)।

नोट: मुझे पता है कि GetCurrentClassLogger() वही जानकारी प्राप्त करता है जो मैं .NET प्रतिबिंब के साथ पुनर्प्राप्त करूंगा।

using NLog; 
using SimpleInjector; 

namespace DependencyInjection 
{ 
    class Program 
    { 
     private static Container _container; 
     static void Main(string[] args) 
     { 
      Bootstrap(); 
      _container.GetInstance<Greeter>().Greet(); 
     } 

     private static void Bootstrap() 
     { 
      _container = new Container(); 

      _container.Register<ILogger>(() => LogManager.GetCurrentClassLogger(), Lifestyle.Transient); 
      _container.Register<Greeter>(); 

      _container.Verify(); 
     } 

     public class Greeter 
     { 
      private ILogger _logger; 

      public Greeter(ILogger logger) 
      { 
       _logger = logger; 
      } 

      public void Greet() 
      { 
       _logger.Log(LogLevel.Info, "Hello world!"); 
      } 
     } 
    } 
} 
+0

आप 'लॉगरनाम' का मूल्य क्या चाहते हैं? – qujck

+1

संबंधित: https://stackoverflow.com/q/32952701/264697 – Steven

+1

एओपी तकनीकों को लागू करना बहुत उपयोगी है, लेकिन कृपया कोड बुनाई उपकरण से दूर रहें। सजावट का उपयोग करके एओपी लागू करें। संबंधित: https://stackoverflow.com/a/9915056/264697 – Steven

उत्तर

7

आपको प्रॉक्सी लॉगर को परिभाषित करने की आवश्यकता है जो संदेश को सही नलॉग लॉगर पर रूट करता है। यह प्रॉक्सी बहुत सरल है:

public class NLogProxy<T> : ILogger 
{ 
    private static readonly NLog.ILogger logger = 
       LogManager.GetLogger(typeof (T).FullName); 

    void ILogger.Log(string message) 
    { 
     logger.Log(LogLevel.Info, message); 
    } 
} 

आप हर जगह आपको लॉग इन करने की जरूरत है कि आप केवल ILogger इंजेक्षन करना होगा के रूप में

container.RegisterConditional(typeof(ILogger), 
    context => typeof(NLogProxy<>).MakeGenericType(context.Consumer.ImplementationType), 
    Lifestyle.Singleton, context => true); 

इस रजिस्टर कर सकते हैं।

एओपी के लिए। मुझे यकीन है कि इस टिप्पणी से आपका क्या मतलब है

एक रैपर जिसे बनाए रखा जाना है (NLog.ILogger अनुबंध विशाल है)।

लॉगिंग एक cross cutting concern है और एक decorator का उपयोग कर पार काटने चिंताओं लागू करने के लिए एक शानदार तरीका है। एक सजावट के साथ प्रत्येक (निजी) फ़ंक्शन कॉल प्रवेश और बाहर निकलना लॉग करना संभव नहीं होगा लेकिन आप उसे क्यों चाहेंगे? जैसा कि आप here पढ़ सकते हैं, आपको शायद इसकी आवश्यकता नहीं है। सरल तथ्य यह है कि एक सेवा को कॉल किया जाता है (इस सेवा में पारित डेटा के साथ) और अधिकांश मामलों में पूर्ण स्टैकट्रैक के साथ संभावित अपवाद लॉग किए जाते हैं।

तो इस पर विचार करें:

public interface ISomeService 
{ 
    void DoSomething(string someParameter); 
} 

public class SomeServiceDecorator : ISomeService 
{ 
    private readonly ISomeService decoratee; 
    private readonly ILogger logger; 

    public SomeServiceDecorator(ISomeService decoratee, ILogger logger) 
    { 
     this.decoratee = decoratee; 
     this.logger = logger; 
    } 

    public void DoSomething(string someParameter) 
    { 
     try 
     { 
      this.logger.Log(string.Format("Do something called with {0}", someParameter)); 
      this.decoratee.DoSomething(someParameter); 
     } 
     catch (Exception e) 
     { 
      this.logger.Log(e.ToString());     
      throw; 
     } 
    } 
} 

यह डेकोरेटर सभी कार्य सूचना सेवा के लिए पारित साथ कहता है और ऐसी कोई भी अपवाद प्रवेश करेंगे प्रवेश करेंगे।

लेकिन यह दृष्टिकोण 2 से कक्षाओं की संख्या में वृद्धि करेगा, इसलिए DRY नहीं। यह समस्या इसलिए होती है क्योंकि यह डिज़ाइन कम से कम उप-स्थानिक है। एक खुले जेनेरिक अमूर्तता के आसपास एक डिजाइन का उपयोग पूरी तरह से इस समस्या को हल करेगा। आप इस डिजाइन here और here के बारे में पढ़ सकते हैं।

इस मामले में आप एक ही `

public class LoggingCommandHandlerDecorator<T> : ICommandHandler<T> 
{ 
    private readonly ICommandHandler<T> decoratee; 
    private readonly ILogger logger; 

    public LoggingCommandHandlerDecorator(ICommandHandler<T> decoratee, ILogger logger) 
    { 
     this.decoratee = decoratee; 
     this.logger = logger; 
    } 

    public void Handle(T command) 
    { 
     // serialize command to json and log 
     this.logger.Log(serializedcommandData); 
     this.decoratee.Handle(command); 
    } 
} 

रूप LoggingDecorator 'और यह एक डेकोरेटर अपने सभी आदेशों प्रवेश करेंगे होगा।

यह एओपी का मेरा दृष्टिकोण है ....

+1

@ रिच-नेट मुझे लगता है कि आपका उत्तर न केवल स्टीवन टिप्पणियों को संबोधित करता है बल्कि लॉग इन करने पर जेफ एटवुड के लेवल पर भी प्रकाश डाला गया है: [लॉगिंग के साथ समस्या] (http://blog.codinghorror.com/the-problem-with-logging/)। किसी भी वास्तुकार को सौदा करने के लिए एक दिलचस्प पुरानी लेकिन अच्छी चर्चा है। –

+0

वास्तव में सहायक, धन्यवाद – james

संबंधित मुद्दे