是的,当您将值传递给转换器时,它将成为string
Enum (EnumConverter) 的默认类型转换器,因为GetStandardValues
(ie Enum.GetValues()
) 将字段的可枚举作为字符串返回。
解决此问题的最佳方法是编写自定义类型转换器来装饰您的枚举。幸运的是,您不是第一个需要此功能的人,请参阅下面的代码示例。
public class EnumTypeConverter : EnumConverter
{
public EnumTypeConverter()
: base(typeof(Enum))
{
}
public EnumTypeConverter(Type type)
: base(type)
{
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || TypeDescriptor.GetConverter(typeof(Enum)).CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string)
return GetEnumValue(EnumType, (string)value);
if (value is Enum)
return GetEnumDescription((Enum)value);
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (value is Enum && destinationType == typeof(string))
return GetEnumDescription((Enum)value);
if (value is string && destinationType == typeof(string))
return GetEnumDescription(EnumType, (string)value);
return base.ConvertTo(context, culture, value, destinationType);
}
public static bool GetIsEnumBrowsable(Enum value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
var attributes = (BrowsableAttribute[])fieldInfo.GetCustomAttributes(typeof(BrowsableAttribute), false);
return !(attributes.Length > 0) || attributes[0].Browsable;
}
public static string GetEnumDescription(Enum value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
return (attributes.Length > 0) ? attributes[0].Description : value.ToString();
}
public static string GetEnumDescription(Type value, string name)
{
var fieldInfo = value.GetField(name);
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
return (attributes.Length > 0) ? attributes[0].Description : name;
}
public static object GetEnumValue(Type value, string description)
{
var fields = value.GetFields();
foreach (var fieldInfo in fields)
{
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0 && attributes[0].Description == description)
return fieldInfo.GetValue(fieldInfo.Name);
if (fieldInfo.Name == description)
return fieldInfo.GetValue(fieldInfo.Name);
}
return description;
}
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
return base.GetStandardValues(context);
}
}
用法
[TypeConverter(typeof(EnumTypeConverter))]
public enum UserTypes : int
{
[Browsable(false)]
Unkown,
[Description("Local")]
LocalUser,
[Description("Network")]
NetworkUser,
[Description("Restricted")]
RestrictedUser
}
如您所见,上面的枚举我们使用Description
属性来装饰每个字段,并使用用户朋友描述,并覆盖类型转换器以首先查找此属性。
不是 100%,但要让它与您的代码一起使用,您还需要将您的代码更改MarkupExtension
为以下内容(注意:我尚未对此进行测试,因此需要您做一些工作)。
[MarkupExtensionReturnType(typeof (IEnumerable))]
public class EnumValuesExtension : MarkupExtension {
public EnumValuesExtension() {}
public EnumValuesExtension(Type enumType)
{
this.EnumType = enumType;
}
[ConstructorArgument("enumType")]
public Type EnumType { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (this.EnumType == null)
throw new ArgumentException("The enum type is not set");
var converter = TypeDescriptor.GetConverter(this.EnumType);
if (converter != null && converter.GetStandardValuesSupported(this.EnumType))
return converter.GetStandardValues(this.EnumType);
return Enum.GetValues(this.EnumType);
}
}
此外,我只对应用程序进行了有限的本地化,但我相信这是最好和最可维护的方法,因为它能够利用现有的 .NET 本地化工具(例如卫星程序集)