c#属性带参数的解决方案
本文关键字:解决方案 参数 属性 | 更新日期: 2023-09-27 18:19:03
我知道c#除了默认属性外不支持带参数的属性。但我认为在某些情况下有这样的功能还是不错的。例如,应用程序可能具有特定于当前使用的语言的设置。因此,这样的设置属性可能看起来像这样。
settings.IsContentDownloaded["en-US"] = true;
虽然默认情况下不支持Event,但我们可以想出一个解决方案,用该语言中可用的其他重要功能来模拟它。但问题是什么是最好的解决方法,提供一个通用的方法来解决这个问题。
我有我自己的解决方法,我已经分享了它作为答案。但是我正在寻找一个更好的方法或任何改进我的方法。
创建一个字典,其中键是您的字符串,如"en-US",值是bool值:
Dictionary<string, bool> aaa = new Dictionary<string, bool>();
aaa.Add("en-US", true);
if(aaa["en-US"].Equals(true))
{
}
这是一个有趣的问题,这是我想到的一个方法:
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
在内部字典中存储本地化的值,这实际上没有什么特别的,但是我添加了一个功能,允许它像普通属性一样使用,隐式转换操作符。
这确实需要一些技巧来使用,但是为了在类中正确使用它,不能使用auto-properties,因为你必须在一个集合上合并两者,而不是覆盖它,所以这里有一个如何在类中使用它的示例:
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>
的隐式转换,然后将其分配给属性,这就是需要合并而不是覆盖的原因。
我在这里留下了几个(大)漏洞,即如果没有找到该区域性的值,该属性应该返回一些默认值(目前它将抛出异常)。但是它展示了一种解决这个问题的方法。
我使用名为_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];
}
}
}