2015-10-23 29 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>的隐式转换,然后将其分配给属性,这就是为什么需要合并而不是覆盖。

我在这里留下了几个(大)的漏洞,即如果没有找到该文化的值(当前它将抛出异常),该属性应该返回一些默认值。但它显示了解决这个问题的一种方法。