我的每个成员都有一个DescriptionAttribute
的枚举。
由于我无法通过WCF发送此DescriptionAttribute
(这很难学习),我一直在尝试创建一个方法,向我发送带有描述的字典。
经过一番努力,我在WCF服务中提出了这个方法:
public IDictionary<Enum, string> GetEnumDescriptionsList(string enumtype)
{
Type t = Type.GetType(enumtype);
if (t.BaseType != typeof(Enum))
{
return null;
}
var returnvalue = new Dictionary<Enum, string>();
foreach (Enum value in Enum.GetValues(t))
{
returnvalue.Add(value, value.GetDescription());
}
return returnvalue;
}
对方法的调用:
var myDict = GetEnumDescriptionsList(typeof (UserType).ToString());
当我在与该方法相同的类中进行调用时,这可以正常工作,但是当我通过WCF进行调用时,我返回了null。
调试后,我发现string-parameter包含“不正确”的值。我的意思是客户端上的UserType.ToString()
具有与WCF服务中的名称空间不同的名称空间。
阅读this post解释了这个问题。
此时此刻我已经陷入困境:泛型不可能,将类型作为Type
类型的参数发送是不可能的(see this post),...
最后一个选择是为我拥有的每个Enum编写一个方法(目前只有9个),但我觉得有一个比这更好的方法。
提前致谢。
更新 使用@KeithS提供的解决方案我有以下代码来创建字典:
Assembly asm = Assembly.GetExecutingAssembly();
foreach (Type type in asm.GetTypes())
{
if (type.IsEnum)
{
enumTypeNames.Add(type.Name, type.AssemblyQualifiedName);
}
}
webservice中的方法为给定类型的每个枚举成员返回一个dict:
public IDictionary<string, string> GetEnumDescriptionsList(string enumtypename)
{
var enumtypenames = EnumMethods.GetEnumTypeNames();
var returnvalue = new Dictionary<string, string>();
string fullyQualifiedTypeName;
enumtypenames.TryGetValue(enumtypename, out fullyQualifiedTypeName);
var enumType = Type.GetType(fullyQualifiedTypeName);
foreach (Enum value in Enum.GetValues(enumType))
{
returnvalue.Add(value.ToString(), value.GetDescription());
}
return returnvalue;
}
来自客户的电话:
var returnvalue = client.GetEnumDescriptionsList(typeof(UserType).Name);
除了我几天前发布的问题外,它就像魅力一样:Name of enum in innerclass changes through WCF-service
当我从客户端拨打电话时:
var returnvalue = client.GetEnumDescriptionsList(typeof(ActionsMailDirectLinkContent).Name);
它的名称为“ActionsMailDirectLinkContent
”,但在我的enumtypes字典中,我有“MailDirectLinkContent
”。
所以我的问题是,如果有办法避免这种情况,或者我必须将我的枚举作为唯一的解决方案从动作类中删除。
更新2: 正如@KeithS在他的评论中提到的那样,我不得不将Enums带出我的班级。我把它们放在一个子文件夹中,所以它们仍然是“分组”的,但上面的方法对所有的枚举都是这样的。
Thx Keith。
答案 0 :(得分:3)
如果您可以安全地假设不需要命名空间来使Enum类型的名称唯一(换句话说,您将不会也不会有两个名为“MyEnum”的枚举,您将要关注),可以设置一个Dictionary<string,string>
键入“简单”(非限定)枚举类型名称,并包含服务器端每个枚举类型的完全限定名称。然后,您只需将简单的Enum类型名称传递给您的方法,然后通过Dictionary运行它以生成您获取并返回值的“真实”类型名称,客户端和服务器之间的任何命名空间差异都无关紧要。
字典甚至可以动态生成,因此它需要较少的维护,但是您可能会遇到扫描枚举类型的程序集的问题(如果只有一个程序集或命名空间包含您关心的所有枚举,则会有所帮助)
答案 1 :(得分:3)
我已经尝试但仍未通过WCF获取描述属性。
我使用了以下
[DataContract(Name = "HorseDNAKitRequest.RequestReasonSubType")]
public enum RequestReasonSub : byte {
[EnumMember(Value = "HERDA")]
HERDA = 1,
[EnumMember(Value = "HYPP")]
HYPP = 2,
[EnumMember(Value = "GBED")]
GBED = 3,
[EnumMember(Value = "OLWS")]
OLWS = 4,
[EnumMember(Value = "Red Factor And Agouti")]
RedFactorandAgouti = 5,
[EnumMember(Value = "Red Factor")]
RedFactor = 6,
[EnumMember(Value = "Agouti")]
Agouti = 7,
[EnumMember(Value = "Cream")]
Cream = 8,
[EnumMember(Value = "Pearl")]
Pearl = 9,
[EnumMember(Value = "Dun")]
Dun,
[EnumMember(Value = "Silver")]
Silver,
[EnumMember(Value = "Gray")]
Gray,
[EnumMember(Value = "Tobiano")]
Tobiano,
[EnumMember(Value = "Sabino")]
Sabino,
}
使用扩展方法获取价值。
public static string GetEnumDescription(this Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
EnumMemberAttribute[] attributes =
(EnumMemberAttribute[])fi.GetCustomAttributes(
typeof(EnumMemberAttribute),
true);
if (attributes != null && attributes.Length > 0)
if (attributes[0].Value != null)
return attributes[0].Value;
else
return value.ToString();
else
return value.ToString();
}
完美无缺
答案 2 :(得分:0)
有一个技巧,在合同中以这种方式定义你的枚举:
public enum EPaymentCycle
{
[EnumMember(Value = "Month by Month")]
Monthly,
[EnumMember(Value = "Week by Week")]
Weekly,
[EnumMember(Value = "Hour by Hour")]
Hours
}
SvcUtils序列化产生了一个有趣的结果:
public enum EPaymentCycle : int
{
[System.Runtime.Serialization.EnumMemberAttribute(Value="Month by Month")]
MonthByMonth= 0,
[System.Runtime.Serialization.EnumMemberAttribute(Value="Week by Week")]
WeekbyWeek= 1,
[System.Runtime.Serialization.EnumMemberAttribute(Value="Hour by Hour")]
HourbyHour = 2
}
您可以通过反射阅读EnumMemberAttribute值,并获得它。 svcutil序列化生成的xsd元数据文件也是预期的:
<xs:simpleType name="EPaymentCycle">
<xs:restriction base="xs:string">
<xs:enumeration value="Month by Month" />
<xs:enumeration value="Week by Week" />
<xs:enumeration value="Hour by Hour" />
</xs:restriction>