我有一个项目,其中我有一些实现抽象类的程序集。
每个程序集都有一个名为ResultEnum的公共枚举。 此ResultEnum的值作为int存储在数据库中。
我有另一个显示一些信息的web项目,我希望它也显示这个int的字符串表示 - 来自ResultEnum的相应值的名称。
我想要做的是,使用MEF,加载所有相关的程序集(这里没问题),使用反射搜索这个枚举(这里也没问题),然后以某种方式存储枚举,并将其缓存在下次我想将int从数据库转换为字符串表示(以及必要时反过来),以避免所有这个过程,因为我的db表中有数千条记录。
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(path));
_container = new CompositionContainer(catalog);
try
{
_container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
}
foreach (var task in myTasks)
{
TaskAbstract instance = (TaskAbstract)task.CreateExport().Value;
MemberInfo[] infos = instance.GetType().GetMembers(BindingFlags.Public | BindingFlags.Static);
foreach (MemberInfo member in infos.Where(x => x.Name.Equals("ResultEnum")))
{
Console.WriteLine(member);
}
}
您认为下一步应该是什么? 我该如何存储/缓存它?
由于
答案 0 :(得分:1)
除了@ Thomas的回答:
使用反射可以从属性中获取精确的int值,可以使用下一个表达式获取该具体值的名称:
var enumValueName = Enum.GetName(member.GetType(), member.GetValue(instance));
<强> UPD 强>
我真的很想你反映了MemberInfos。要应用我的解决方案,您可以通过以下方式更新反射:
foreach (var task in myTasks)
{
TaskAbstract instance = (TaskAbstract)task.CreateExport().Value;
// Reflect properties, not all members
PropertyInfo[] infos = instance.GetType().GetProperties(BindingFlags.Public | BindingFlags.Static);
foreach (PropertyInfo prop in infos.Where(x => x.Name.Equals("ResultEnum")))
{
var enumValueName = Enum.GetName(prop.GetType(), prop.GetValue(instance));
}
}
或者您可以将MemberInfo转换为PropertyInfo。
答案 1 :(得分:1)
解决此问题的一种方法是考虑使用可子类化的枚举技术(有时也称为多态枚举)。
我写了几个泛型类专门用来支持这些类型,你可以阅读here。此外,已向Github上的Roslyn编译器团队提交了proposal,以便为C#添加对这些类型枚举的支持。
以下是一组子类可用枚举的示例,它使用我项目中的类,有两个基础类型,字符串和整数:
public sealed class Status : StringIntegerEnum<Status>
{
public static readonly Status Active = new Status("active", 1);
public static readonly Status Inactive = new Status("inactive", 0);
private Status(string status, int statusCode) : base(status, statusCode) {}
}
请注意,字符串值不与常量名称本身相同,这允许您使用基本字符串值,其字符违反C#中的常规命名约定。
StringIntegerEnum<tStringIntegerEnum>
基类提供.AllValues
,.AllNaturalValues
和.AllStringValues
个静态方法,您可以使用这些方法枚举枚举值列表或其基础值的两种类型。
答案 2 :(得分:0)
来自你的评论:
我同意,但问题是如何迭代枚举器的值和名称
我认为你的意思是“枚举”,而不是“枚举”。您可以使用Enum.GetValues
方法:
var valuesToNames =
Enum.GetValues(enumType)
.Cast<object>()
.ToDictionary(o => (int)o, o => Enum.GetName(enumType, o));
而且,有没有比字典更好的解决方案
更好的方法?我认为字典是一个很好的解决方案;你有什么理由想要别的吗?
答案 3 :(得分:0)
这就是我最终编写代码的方式:
resultEnumsForTasks = new Dictionary<string, Dictionary<UInt16, string>>();
foreach (var task in myTasks)
{
Dictionary<UInt16, string> _enum = new Dictionary<UInt16,string>();
TaskAbstract instance = (TaskAbstract)task.CreateExport().Value;
MemberInfo resultEnum = instance.GetType().GetMember("ResultEnum").FirstOrDefault();
if (resultEnum == null)
continue;
string[] names = Enum.GetNames(resultEnum as Type);
IList<int> vals = (IList<int>)Enum.GetValues(resultEnum as Type);
for (int i = 0; i < names.Length; i++)
{
_enum.Add(Convert.ToUInt16(vals[i]), names[i]);
}
resultEnumsForTasks.Add(instance.GetType().Name, _enum);
}
这与@ n.turakulov的解决方案非常相似,但是他的解决方案对我来说不起作用,因为我出于某种原因获得了PropertyInfo的空列表...
感谢所有协助的人!