2011-01-10 12 views
5

मैं एक ऐसे वेब एप्लिकेशन पर काम कर रहा हूं जिसे मुझे स्थानीयकरण और अंतर्राष्ट्रीयकरण की आवश्यकता है। यह मेरे लिए हुआ कि मैं एक निर्भरता इंजेक्शन ढांचे का उपयोग कर ऐसा कर सकता था। के मैं एक अंतरफलक ILocalResources घोषित कहना (इस उदाहरण के लिए सी # का उपयोग कर, लेकिन यह वास्तव में महत्वपूर्ण नहीं है) करते हैं:एक डी ढांचे का उपयोग कर स्थानीयकरण - अच्छा विचार?

interface ILocalResources { 
    public string OkString { get; } 
    public string CancelString { get; } 
    public string WrongPasswordString { get; } 
    ... 
} 

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

क्या कोई कारण है कि मुझे इस तरह की चीज़ के लिए डीआई फ्रेमवर्क का उपयोग नहीं करना चाहिए? एकमात्र आपत्ति जो मैं खुद को पा सकता हूं वह यह है कि यह थोड़ा अधिक हो सकता है, लेकिन यदि मैं अपने वेब ऐप में डीआई फ्रेमवर्क का उपयोग कर रहा हूं, तो भी मैं इसे अंतर्राष्ट्रीयकरण के लिए भी उपयोग कर सकता हूं?

उत्तर

2

यदि आप मौजूदा संसाधन ढांचे (जैसे कि एएसपी.NET में निर्मित) का उपयोग नहीं कर सकते हैं और आपको अपना खुद का निर्माण करना होगा, तो मुझे लगता है कि आपको किसी बिंदु पर स्थानीय संसाधन प्रदान करने वाली सेवाओं का पर्दाफाश करने की आवश्यकता होगी।

डी ढांचे का उपयोग सेवा त्वरण को संभालने के लिए किया जाता है। आपका स्थानीयकरण ढांचा स्थानीयकरण प्रदान करने वाली सेवाओं का पर्दाफाश करेगा। फ्रेमवर्क द्वारा उस सेवा को क्यों नहीं रखा जाना चाहिए?

यहां अपने उद्देश्य के लिए डी का उपयोग नहीं करना है, "मैं एक सीआरएम ऐप बना रहा हूं लेकिन DI का उपयोग नहीं कर सकता क्योंकि DI ग्राहक संबंध प्रबंधन के लिए नहीं बनाया गया है"।

तो हाँ, यदि आप पहले से ही अपने शेष एप्लिकेशन में DI का उपयोग कर रहे हैं, तो आईएमओ स्थानीयकरण को संभालने वाली सेवाओं के लिए इसका उपयोग नहीं करना गलत होगा।

2

एकमात्र नुकसान जो मैं देख सकता हूं वह यह है कि "संसाधनों" के किसी भी अपडेट के लिए, आपको संसाधनों वाली असेंबली को फिर से सम्मिलित करना होगा। और आपकी परियोजना के आधार पर, यह नुकसान केवल मूल्यों की बजाय किसी प्रकार की संसाधन सेवा को हल करने के लिए डीआई फ्रेमवर्क का उपयोग करने की अच्छी सलाह हो सकता है।

6

निर्भरता इंजेक्शन करने के लिए एक डी ढांचा बनाया गया है और स्थानीयकरण केवल आपकी सेवाओं में से एक हो सकता है, इसलिए उस मामले में डीआई फ्रेमवर्क आईएमओ का उपयोग करने के लिए कोई कारण नहीं है। शायद हमें प्रदत्त ILocalResources इंटरफेस पर चर्चा करना शुरू कर देना चाहिए। जबकि मैं समय समर्थन संकलित करने का पक्ष हूं, मुझे यकीन नहीं है कि आपूर्ति इंटरफ़ेस आपकी मदद करेगा, क्योंकि वह इंटरफ़ेस शायद आपके सिस्टम में प्रकार होगा जो सबसे अधिक बदल जाएगा। और उस इंटरफेस के साथ इसे लागू करने वाले प्रकार/प्रकार। शायद आपको एक अलग डिजाइन के साथ जाना चाहिए।

जब हम अधिकतर स्थानीयकरण ढांचे/प्रदाताओं/कारखानों (या जो कुछ भी) देखते हैं, तो वे सभी स्ट्रिंग आधारित होते हैं। इस की वजह से, निम्नलिखित डिजाइन के बारे में सोचना:

public interface ILocalResources 
{ 
    string GetStringResource(string key); 
    string GetStringResource(string key, CultureInfo culture); 
} 

यह आपको इंटरफ़ेस बदले बिना, संदेश निहित डेटा संग्रह के लिए कुंजी और संस्कृतियों को जोड़ने के लिए अनुमति होगी। डाउनसाइड निश्चित रूप से है कि आपको कभी भी एक कुंजी नहीं बदलनी चाहिए, क्योंकि यह शायद नरक होगा।

एक और दृष्टिकोण एक सार आधार प्रकार हो सकता है:

public abstract class LocalResources 
{ 
    public string OkMessage { get { return this.GetString("OK"); } } 
    public string CancelMessage { get { return this.GetString("Cancel"); } } 
    ... 

    protected abstract string GetStringResource(string key, 
     CultureInfo culture); 

    private string GetString(string key) 
    { 
     Culture culture = CultureInfo.CurrentCulture; 

     string resource = GetStringResource(key, culture); 

     // When the resource is not found, fall back to the neutral culture. 
     while (resource == null && culture != CultureInfo.InvariantCulture) 
     { 
      culture = culture.Parent; 
      resource = this.GetStringResource(key, culture); 
     } 

     if (resource == null) throw new KeyNotFoundException(key); 

     return resource; 
    } 
} 

और इस प्रकार के क्रियान्वयन ऐसा दिखाई दे सकता है: क्योंकि चाबियाँ जीता,

public sealed class SqlLocalResources : LocalResources 
{ 
    protected override string GetStringResource(string key, 
     CultureInfo culture) 
    { 
     using (var db = new LocalResourcesContext()) 
     { 
      return (
       from resource in db.StringResources 
       where resource.Culture == culture.Name 
       where resource.Key == key 
       select resource.Value).FirstOrDefault(); 
     } 
    } 
} 

यह दृष्टिकोण दोनों दुनिया के सर्वश्रेष्ठ लेता है ' आवेदन के माध्यम से बिखरे हुए नहीं हैं और नई संपत्तियों को जोड़ना सिर्फ एक ही स्थान पर किया जाना है।

container.RegisterSingleton<LocalResources>(new SqlLocalResources()); 

और चूंकि LocalResources प्रकार ठीक एक सार विधि है कि सब काम करता है, यह एक डेकोरेटर कि अनुरोध कर रहा रोकने के लिए कैशिंग कहते हैं बनाने के लिए आसान है: अपने favorite डि पुस्तकालय का उपयोग करना, आप इस तरह एक कार्यान्वयन रजिस्टर कर सकते हैं

public sealed class CachedLocalResources : LocalResources 
{ 
    private readonly Dictionary<CultureInfo, Dictionary<string, string>> cache = 
     new Dictionary<CultureInfo, Dictionary<string, string>>(); 
    private readonly LocalResources decoratee; 

    public CachedLocalResources(LocalResources decoratee) { this.decoratee = decoratee; } 

    protected override string GetStringResource(string key, CultureInfo culture) { 
     lock (this.cache) { 
      string res; 
      var cultureCache = this.GetCultureCache(culture); 
      if (!cultureCache.TryGetValue(key, out res)) { 
       cultureCache[key] = res= this.decoratee.GetStringResource(key, culture); 
      }     
      return res; 
     } 
    } 

    private Dictionary<string, string> GetCultureCache(CultureInfo culture) { 
     Dictionary<string, string> cultureCache; 
     if (!this.cache.TryGetValue(culture, out cultureCache)) { 
      this.cache[culture] = cultureCache = new Dictionary<string, string>(); 
     } 
     return cultureCache; 
    } 
} 

आप डेकोरेटर के रूप में इस आवेदन कर सकते हैं: डेटाबेस से एक ही डेटा

container.RegisterSingleton<LocalResources>(
    new CachedLocalResources(new SqlLocalResources())); 

नहीं ई कि यह सजावटी स्ट्रिंग संसाधनों को अनिश्चित काल तक कैश करता है, जो स्मृति रिसाव का कारण बन सकता है, इसलिए आप तारों को WeakReference उदाहरणों में लपेटना चाहते हैं या इस पर किसी प्रकार का समाप्ति समय समाप्ति करना चाहते हैं। लेकिन विचार यह है कि आप मौजूदा कार्यान्वयन को बदलने के बिना कैशिंग लागू कर सकते हैं।

मुझे उम्मीद है कि इससे मदद मिलती है।

+0

वैकल्पिक रूप से आप 'ILocalResources 'इंटरफ़ेस के लिए एक्सटेंशन विधियों को भी कार्यान्वित कर सकते हैं, लेकिन नकारात्मकता यह है कि आपके पास गुणों के बजाय विधियां होंगी। लेकिन शायद वह बुरा नहीं होगा। – Steven

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