2015-10-23 28 views
0

我知道C#不支持除默認屬性之外的參數。但我認爲在某些情況下仍然有這樣的功能是很好的。例如,應用程序可能具有特定於當前所用語言的設置。所以這樣的設置屬性可能看起來像這樣。帶參數的C#屬性的解決方法

settings.IsContentDownloaded["en-US"] = true; 

事件想到這個默認不支持,我們可以想出一個解決辦法對於語言中可用的其他偉大的功能來模擬這一點。但問題是提供這個問題的一般方法的最佳解決方法是什麼。

我有我自己的解決方法,我已經分享它作爲答案。但是我正在尋找一種更好的方法或改進我的方法。

+2

只需使用字典。 – SLaks

回答

0

我已經使用名爲_settingsRepositoty的字典來存儲設置,但它可能是任何用於存儲基於應用程序類型的設置。

public class Settings 
{ 
    private Dictionary<string, object> _settingsRepository = new Dictionary<string, object>(); 

    private LanguageSpecificPropertyFactory _factory; 

    public Settings() 
    { 
     _factory = new LanguageSpecificPropertyFactory(this); 
    } 

    public LanguageSpecificProperty<bool> IsContentDownloaded 
    { 
     get 
     { 
      return _factory.GetLanguageProperty("IsContentDownloaded", false); 
     } 
    } 

    private void Set<T>(string propertyName, string lang, T val) 
    { 
     string fullPropertyName = string.Format("{0}_{1}", propertyName, lang); 
     _settingsRepository[fullPropertyName] = val; 
    } 

    private T Get<T>(string propertyName, string lang, T defaultValue) 
    { 
     string fullPropertyName = string.Format("{0}_{1}", propertyName, lang); 
     if (!_settingsRepository.ContainsKey(fullPropertyName)) 
     { 
      _settingsRepository[fullPropertyName] = defaultValue; 
     } 
     return (T)_settingsRepository[fullPropertyName]; 
    } 

    public class LanguageSpecificProperty<T> 
    { 
     private string _properyName; 

     private T _defaultValue; 

     private Settings _settings; 

     internal LanguageSpecificProperty(Settings settings, string propertyName, T defaultValue) 
     { 
      _properyName = propertyName; 
      _defaultValue = defaultValue; 
     } 

     public T this[string lang] 
     { 
      get 
      { 
       return _settings.Get<T>(_properyName, lang, _defaultValue); 
      } 

      set 
      { 
       _settings.Set<T>(_properyName, lang, value); 
      } 
     } 
    } 

    public class LanguageSpecificPropertyFactory 
    { 
     private Dictionary<string, object> _properties = new Dictionary<string, object>(); 

     private Settings _settings; 

     public LanguageSpecificPropertyFactory(Settings settings) 
     { 
      _settings = settings; 
     } 

     internal LanguageSpecificProperty<T> GetLanguageProperty<T>(string propertyName, T defaultValue) 
     { 
      if (!_properties.ContainsKey(propertyName)) 
      { 
       _properties.Add(propertyName, new LanguageSpecificProperty<T>(_settings, propertyName, defaultValue)); 
      } 
      return (LanguageSpecificProperty<T>)_properties[propertyName]; 
     } 
    } 

} 
1

創建一個字典,其中鍵是你的字符串,如「EN-US」和值是一個布爾值:

Dictionary<string, bool> aaa = new Dictionary<string, bool>(); 

aaa.Add("en-US", true); 

if(aaa["en-US"].Equals(true)) 
{ 

} 
1

它的一個有趣的問題,這裏是我想出了一個方法:

public class LocalizableSetting<T> : IEnumerable<KeyValuePair<string, T>> 
{ 
    private Dictionary<string, T> _values; 

    public T this[string cultureName] 
    { 
     get { return _values[cultureName]; } 
     set 
     { 
      _values[cultureName] = value; 
     } 
    } 

    public IEnumerator<KeyValuePair<string, T>> GetEnumerator() 
    { 
     return _values.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return _values.GetEnumerator(); 
    } 

    public static implicit operator T(LocalizableSetting<T> value) 
    { 
     return value[CultureInfo.CurrentCulture.Name]; 
    } 

    public static implicit operator LocalizableSetting<T>(T value) 
    { 
     var setting = new LocalizableSetting<T>(); 
     setting[CultureInfo.CurrentCulture.Name] = value; 
     return setting; 
    } 
} 

這裏LocalizableSetting存儲在內部的字典,這實在是沒有什麼特別的本地化值,但我增加了一個功能,允許它像普通的屬性可以作爲很好,T他隱式轉換運算符。

這確實需要一些技巧,不過使用,爲了在一個類中正確地使用它,你不能使用自動性能,因爲你必須合併兩個一組,而不是覆蓋它,所以這裏是如何在一類使用它的一個例子:

public class SomeLocalizableClass 
{ 
    //Explicitly declare the backing field for the property! 
    private LocalizableSetting<int> _intSetting = new LocalizableSetting<int>(); 

    public LocalizableSetting<int> IntSetting 
    { 
     get { return _intSetting; } 
     set 
     { 
      //Merge, don't overwrite 
      foreach (var kvp in value) 
       _intSetting[kvp.Key] = kvp.Value; 
     } 
    } 
} 

注意,在set方法中,通過值進行迭代,並且任一覆蓋當前或增加了一個新的(與分度器的幫助下)。

因此,這可以讓你做這樣的事情:

public class SomeConsumerClass 
{ 
    public void SomeMethod() 
    { 
     SomeLocalizableClass c = new SomeLocalizableClass(); 
     c.IntSetting["fr-FR"] = 4;  //Sets the french setting 
     c.IntSetting = 10;    //Sets the current culture setting 

     int multipleSetting = c.IntSetting * c.IntSetting; 
    } 
} 

multipleSetting將是該屬性的當前區域性值的倍數,由於從LocalizableSetting<int>int隱式轉換。 c.IntSetting = 10會導致從源類型(int)到LocalizableSetting<int>的隱式轉換,然後將其分配給屬性,這就是爲什麼需要合併而不是覆蓋。

我在這裏留下了幾個(大)的漏洞,即如果沒有找到該文化的值(當前它將拋出異常),該屬性應該返回一些默認值。但它顯示瞭解決這個問題的一種方法。