带参数的C#属性的解决方法

时间:2015-10-23 17:54:10

标签: c# .net properties

我知道C#不支持带有参数的属性,但默认属性除外。但我认为在某些情况下拥有这样的功能仍然很好。例如,应用程序可能具有特定于当前使用的语言的设置。所以这样的设置属性可能看起来像这样。

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

事件认为默认情况下不支持此功能,我们可以提供一种解决方法,使用该语言中提供的其他强大功能来模拟此功能。但问题是什么是提供这个问题的通用方法的最佳解决方法。

我有自己的解决方法,我已将其作为答案分享。但我正在寻找一种更好的方法或改进我的方法。

3 个答案:

答案 0 :(得分:1)

创建一个字典,其中键是您的字符串,例如" en-US"而值是一个布尔:

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

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

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

}

答案 1 :(得分: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将本地化值存储在内部字典中,这实际上并不特别,但是我添加了一个允许它像普通属性一样使用的功能,即隐式转换运算符。

这确实需要使用一些技巧,为了在类中正确使用它,你不能使用自动属性,因为你必须在一个集合上合并它们,而不是覆盖它,以下是如何在类中使用它的示例:

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;
    }
}

由于从multipleSettingLocalizableSetting<int>的隐式转换,int将是该属性的当前文化值的倍数。 c.IntSetting = 10导致从源类型(int)到LocalizableSetting<int>的隐式转换,然后将其分配给属性,这就是需要合并而不是覆盖的原因。

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

答案 2 :(得分: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];
        }
    }

}