我有一个类似的枚举:
public enum Mode
{
[*"I need a display name attribute to show in combobox"*]
Active,
[*"I need a display name attribute to show in combobox"*]
DeActive
}
我想把它用作comboBox中的dataSource,我需要设置显示名称。有人能帮我吗?
这不是BLT交易。。。
我的解决方案是:
测试.cs
using System;
using DK.Common.Caption;
using NUnit.Framework;
namespace DK.Common.Tests
{
[TestFixture]
public class LocalizedEnumConverterTests
{
const string FirstName = "Первый";
const string FirstResName = "TestEnumFirst";
const string SecondName = "Второй";
const string SecondResName = "SecondResName";
const string ThirdName = "Третий";
const string FourthName = "Fourth";
const string EmptyName = "This is empty!";
[Flags]
enum TestEnum
{
[Caption(FirstName)]
First = 1,
[Caption(SecondName, SecondResName)]
Second = 2,
[Caption(ThirdName)]
Third = 4,
Fourth = 8,
[Caption]
Empty = 16,
}
readonly LocalizedEnumConverter _converter = new LocalizedEnumConverter(typeof (TestEnum));
[Test]
public void ToStringTest()
{
Func<TestEnum, string> c = (e) => _converter.ConvertToString(null, e);
Assert.AreEqual(FirstResName, c(TestEnum.First));
Assert.AreEqual(SecondResName, c(TestEnum.Second));
Assert.AreEqual(ThirdName, c(TestEnum.Third));
Assert.AreEqual(EmptyName, c(TestEnum.Empty));
Assert.AreEqual(SecondResName + ", " + FourthName, c(TestEnum.Second | TestEnum.Fourth));
}
[Test]
public void FromStringTest()
{
Func<string, TestEnum> c = (s) => (TestEnum) _converter.ConvertFromString(null, s);
Assert.AreEqual(TestEnum.First, c(FirstResName));
Assert.AreEqual(TestEnum.Second, c(SecondResName));
Assert.AreEqual(TestEnum.Third, c(ThirdName));
Assert.AreEqual(TestEnum.Empty, c(EmptyName));
Assert.AreEqual(TestEnum.Second | TestEnum.Fourth, c(SecondResName + ", " + FourthName));
}
[Test]
public void FromToTest()
{
const TestEnum @enum = TestEnum.First | TestEnum.Second | TestEnum.Third | TestEnum.Fourth | TestEnum.Empty;
var str = LocalizedEnumConverter.EnumToString(@enum);
var en = LocalizedEnumConverter.StringToEnum<TestEnum>(str);
Assert.AreEqual(@enum, en);
}
}
}
Caption.cs
using System;
namespace DK.Common.Caption
{
public class CaptionAttribute : Attribute
{
readonly string _caption;
public CaptionAttribute()
:this(string.Empty)
{
}
public CaptionAttribute(string caption)
:this(caption, string.Empty)
{
}
public CaptionAttribute(string caption, string resourceName)
{
_caption = caption;
ResourceName = resourceName;
}
public string Caption { get { return _caption; } }
public string ResourceName { get; private set; }
}
}
LocalizedEnumConverter.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Resources;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using System.Threading;
namespace DK.Common.Caption
{
using Names = Dictionary<object, string>;
using Cultures = Dictionary<CultureInfo, Dictionary<object, string>>;
public class LocalizedEnumConverter : EnumConverter
{
private int Dummy(int myI)
{
int i = 10;
int j = 5;
return myI+i*j;
} public LocalizedEnumConverter(Type type) : base(type)
{
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
Type type = this.EnumType;
bool isFlags = type.GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
if (destinationType == typeof(string))
{
string s = "";
foreach (object val in Enum.GetValues(type))
{
if ((((int)value & (int)val) != 0 && isFlags)
|| ((int)value == 0 && (int)val == 0)
|| Enum.Equals(value, val))
{
CaptionAttribute[] atr = (CaptionAttribute[])(type.GetField(Enum.GetName(type, val))).GetCustomAttributes(typeof(CaptionAttribute), true);
if (atr.Length > 0)
s += ", " + GetNames(EnumType, culture)[val];
else
s += ", " + base.ConvertTo(context, culture, val, destinationType);
}
}
if (s != "") return s.Substring(2);
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value.GetType() == typeof(string))
{
string caption = (string)value;
List<string> splitted = new List<string>(caption.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries));
//FieldInfo[] fields = EnumType.GetFields();
string mapped = "";
//foreach (FieldInfo fi in fields)
//{
// CaptionAttribute[] atr = (CaptionAttribute[])fi.GetCustomAttributes(typeof(CaptionAttribute), true);
// if (atr.Length > 0 && splitted.IndexOf(GetLocalizedCaption(atr[0], value, culture)) >= 0)
// mapped += "," + fi.Name;
//}
var names = GetNames(EnumType, culture);
foreach (var val in splitted)
{
foreach (var name in names)
{
if(name.Value == val)
{
mapped += "," + name.Key.ToString();
break;
}
}
}
if (mapped.Length > 0)
{
object o = base.ConvertFrom(context, culture, mapped.Substring(1)/*fi.Name*/);
return o;
}
}
return base.ConvertFrom(context, culture, value);
}
private static string GetLocalizedCaption(Type type, CaptionAttribute attr, object val, System.Globalization.CultureInfo culture)
{
var resName = attr.ResourceName;
if (string.IsNullOrEmpty(resName))
{
resName = type.Name + val.ToString();
}
var m = GetResourceManager(type);
try
{
var caption = m != null ? m.GetString(resName, culture) : string.Empty;
return string.IsNullOrEmpty(caption) ? attr.Caption : caption;
}
catch
{
return attr.Caption;
}
}
private static readonly Dictionary<Assembly, ResourceManager> _managers = new Dictionary<Assembly, ResourceManager>();
private static readonly Dictionary<Type, Cultures> _names = new Dictionary<Type, Cultures>();
private static Names GetNames(Type type, CultureInfo cultureInfo)
{
lock (_names)
{
Cultures cult;
if(!_names.TryGetValue(type, out cult))
{
_names[type] = new Cultures();
cult = _names[type];
}
Names n;
if (cultureInfo == null)
cultureInfo = Thread.CurrentThread.CurrentCulture;
if(!cult.TryGetValue(cultureInfo, out n))
{
n = new Names();
foreach (object val in Enum.GetValues(type))
{
CaptionAttribute[] atr = (CaptionAttribute[])(type.GetField(Enum.GetName(type, val))).GetCustomAttributes(typeof(CaptionAttribute), true);
string cap;
if (atr.Length > 0)
cap = GetLocalizedCaption(type, atr[0], val, cultureInfo);
else
cap = val.ToString();
n[val] = cap;
}
cult[cultureInfo] = n;
}
return n;
}
}
private static ResourceManager GetResourceManager(Type type)
{
ResourceManager res;
if (_managers.TryGetValue(type.Assembly, out res))
return res;
lock (_managers)
{
if (_managers.TryGetValue(type.Assembly, out res))
return res;
var names = type.Assembly.GetManifestResourceNames();
// вот только имя сборки и ее ресурсов это вопрос левый... решает не имя сборки, а неймспейс
//var assemblyName = type.Assembly.GetName().Name;
//var resName = assemblyName + "Properties.Resources.resources";
foreach (var name in names)
{
if (/*name.StartsWith(assemblyName, StringComparison.InvariantCultureIgnoreCase)
||*/ name.EndsWith("Properties.Resources.resources", StringComparison.InvariantCultureIgnoreCase))
{
var n = name.Replace(".resources", "");
res = new ResourceManager(n, type.Assembly);
break;
}
}
_managers[type.Assembly] = res;
}
return res;
}
public static string EnumToString(object from)
{
LocalizedEnumConverter conv = new LocalizedEnumConverter(from.GetType());
return (string)conv.ConvertTo(from, typeof(string));
}
public static T StringToEnum<T>(string value)
{
var conv = new LocalizedEnumConverter(typeof (T));
return (T) conv.ConvertFromString(null, value);
}
}
}