以某种方式获取Enum描述“一般”在WCF上

时间:2011-08-08 17:56:40

标签: c# wcf enums

我的每个成员都有一个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。

3 个答案:

答案 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>