2009-12-21 5 views
10

मैं निम्नलिखित इंटरफेस है:log4net आवरण के साथ structuremap का उपयोग

public interface ILogger 
{ 
    void Debug(string message, params object[] values); 
    void Info(string message, params object[] values); 
    void Warn(string message, params object[] values); 
    void Error(string message, params object[] values); 
    void Fatal(string message, params object[] values); 
} 

और निम्नलिखित कार्यान्वयन:

public class Log4netLogger : ILogger 
{ 
    private ILog _log; 

    public Log4netLogger(Type type) 
    { 
     _log = LogManager.GetLogger(type); 
    } 

    public void Debug(string message, params object[] values) 
    { 
     _log.DebugFormat(message, values); 
    } 

    // other logging methods here... 

} 

मेरा विचार का प्रकार उपयोग करने के साथ Log4netLogger वर्ग का दृष्टांत को structuremap का उपयोग किया गया कक्षा जो लॉगिंग किया था। हालांकि, मैं अपने जीवन के लिए यह नहीं समझ सकता कि कॉलिंग क्लास के प्रकार को किस प्रकार पास करना है ताकि इसे लॉगिंग कार्यान्वयन के निर्माता को पास किया जा सके। यह कैसे करना है (या एक बेहतर तरीका) पर कोई सलाह सबसे सराहना की जाएगी।

उत्तर

1

यदि प्रकार पैरामीटर संदर्भ-विशिष्ट है, तो मुझे नहीं लगता कि यह दिखाए गए अनुसार काम करने जा रहा है।

public interface ILoggerFactory 
{ 
    ILogger Create(Type type); 
} 

public class LoggerFactory : ILoggerFactory 
{ 
    public ILogger Create(Type type) 
    { 
     return new Log4netLogger(type); 
    } 
} 

यह संभव हो सकता है StructureMap bootstrap करने के लिए आपूर्ति करने के लिए: यदि आप कुछ संदर्भ निर्माता में विशिष्ट पारित करने के लिए की जरूरत है, आप की संभावना एक कारखाने इंटरफेस और कार्यान्वयन कि ILogger का एक उदाहरण देता है बनाने के लिए जा रहे हैं उदाहरण के लिए आप इस प्रकार के आधार पर चाहते हैं, लेकिन यह सीमित प्रकार के प्रकार मानता है जिन्हें आप पहले से जानते हैं।

+1

संरचना मैप का उपयोग करते समय कारखानों की आवश्यकता आमतौर पर कारखाने विधि के रूप में लैम्ब्डा के साथ "निर्मित" का उपयोग करके समाप्त की जा सकती है। http://structuremap.sourceforge.net/InstanceExpression.htm#section13 – KevM

1

मुझे वास्तव में अपने स्वयं के प्रश्न का उत्तर देने की आदत से बाहर निकलने की ज़रूरत है, लेकिन जो लोग इसे पार करते हैं, उनके लिए यहां जवाब है।

return ObjectFactory.With(type).GetInstance<T>(); 

मैं वास्तव में structuremap करने के लिए (मेरे ऐप पर structuremap निर्भरता उजागर से बचने के लिए) एक आवरण है कि ऐसा दिखाई देता है:

public static class ServiceManager 
{ 
    public static T Get<T>() 
    { 
     return ObjectFactory.GetInstance<T>(); 
    } 

    public static T Get<T>(Type type) 
    { 
     return ObjectFactory.With(type).GetInstance<T>(); 
    } 
} 

कोड मैं एक लकड़हारा की जरूरत है किसी भी समय, मैं फोन निम्नलिखित:

ServiceManager.Get<ILogger>(GetType()).Info("Logging page view..."); 
+1

मुझे वास्तव में नहीं लगता कि लॉगर को वैश्विक सेवा (क्योंकि यह आमतौर पर क्रॉस-कटिंग) पर विचार करने में कुछ भी गलत है, लेकिन यह स्थिर निर्भरता बनाता है आपके सेवा प्रबंधक पर। मैं यह नहीं कह रहा हूं कि आपका समाधान गलत है (इससे दूर), लेकिन यह थोड़ा सा लगता है जैसे यह वैश्विक सेवा लोकेटर "एंटी-पैटर्न" की तरफ हो सकता है। अनिवार्य रूप से ILogger (या ILoggerFactory) पर आपकी निर्भरता अब स्पष्ट हो सकती है (या हो सकती है)। –

+0

दिलचस्प बिंदु फिल। मुझे यकीन नहीं है कि विकल्प क्या होगा (आईओसी पर वास्तुशिल्प सिफारिशें वास्तव में दुर्लभ हैं)। मेरे मामले में, कक्षा एक HttpHandler है जिसे ILMger तक पहुंच की आवश्यकता है, यह ServiceManager से अनुरोध कर रहा है। मैं और कैसे लागू करूं? – Chris

+0

मैं वास्तुकला की सिफारिशों पर पूरी तरह से सहमत हूं, और आपका प्रश्न आईएमएचओ * * सबसे आम बाधा है जब लोग एक डी ढांचे के साथ शुरू कर रहे हैं। एक अमूर्त फैक्ट्री बनाना सबसे अच्छा जवाब है जिसके साथ मैं आया हूं, और मैं अक्सर स्ट्रक्चर मैप (ऑब्जेक्टफैक्टरी.गेट इंस्टेंस) का उपयोग करके फैक्ट्री को कार्यान्वित करता हूं ताकि श्रृंखला के नीचे निर्भरताएं अभी भी कंटेनर-प्रबंधित हो सकें। यह * सही * नहीं हो सकता है, लेकिन कम से कम निर्भरता स्पष्ट रखी जाती है। –

23

हम log4net के आस-पास एक समान ILogger wrapper का उपयोग करते हैं और आमतौर पर कन्स्ट्रक्टर इंजेक्शन का उपयोग करते हैं। हम लॉगर बनाने के लिए जिम्मेदार फैक्ट्री विधि के रूप में एक इंटरसेप्टर का उपयोग करते हैं। लॉगिंग सेटअप के लिए हमारी सामान्य रजिस्ट्री यहां दी गई है।

public class CommonsRegistry : Registry 
{ 
    public CommonsRegistry() 
    { 
     For<ILogger>() 
      .AlwaysUnique() 
      .TheDefault.Is.ConstructedBy(s => 
      { 
       if (s.ParentType == null) 
        return new Log4NetLogger(s.BuildStack.Current.ConcreteType); 

       return new Log4NetLogger(s.ParentType); 
      }); 

     var applicationPath = Path.GetDirectoryName(Assembly.GetAssembly(GetType()).Location); 
     var configFile = new FileInfo(Path.Combine(applicationPath, "log4net.config")); 
     XmlConfigurator.ConfigureAndWatch(configFile); 
    } 
} 

कंक्रीट प्रकारों पर निर्भरता होने पर मूल प्रकार की शून्य जांच आवश्यक है।

बाकी वैकल्पिक लॉग 4नेट सेटअप सामग्री है।

एक चीज जो मुझे इस सेटअप के बारे में पसंद है वह यूनिट परीक्षण के लिए शून्य लॉगर्स का उपयोग करने की क्षमता है।

+0

दिलचस्प, मुझे इसे आजमा देना होगा। धन्यवाद! – Chris

+0

यह वास्तव में दिलचस्प है। मैंने आपके जवाब पर भी आपकी टिप्पणी देखी। क्या यह काम करेगा अगर सीटीओ निर्भरता कॉलिंग क्लास के प्रकार के बाहर कुछ भी थी? संदर्भ-विशिष्ट सीटीओ निर्भरताओं पर एक ब्लॉग पोस्ट देखना पसंद करेंगे, क्योंकि इसे डी फ्रेमवर्क का उपयोग करने के बारे में # 1 सबसे अधिक पूछे जाने वाले प्रश्न होना चाहिए। –

+0

इसके अलावा, मैं इस बात से संघर्ष कर रहा हूं कि यह समाधान निर्भरता को कम स्पष्ट करता है या नहीं। अगर निर्माण के लिए वास्तव में एक कारखाने की आवश्यकता होती है, तो क्या यह एक अच्छा विचार है कि फैक्ट्री को कॉन्फ़िगरेशन कोड में "छुपाएं", एक अमूर्त फैक्ट्री पर निर्भरता को स्पष्ट करने के बजाय? (मेरा मतलब यह सैद्धांतिक प्रश्न के रूप में है, जरूरी नहीं कि क्रिस के लिए सबसे अच्छा समाधान या प्रति लॉगिंग के लिए)। –