【问题标题】:How do I check enum property when the property is obtained from dynamic in C#?从 C# 中的动态获取属性时,如何检查枚举属性?
【发布时间】:2015-03-04 11:42:49
【问题描述】:

假设我知道一个对象的属性Color 返回一个看起来像这样的枚举:

enum ColorEnum {
   Red,
   Green,
   Blue
};

并且我想检查未知类型的特定对象(我知道具有Color 属性)是否将Color 设置为Red。如果我知道对象类型,我会这样做:

ObjectType thatObject = obtainThatObject();
if( thatObject.Color == ColorEnum.Red ) {
   //blah
}

问题是我没有 ColorEnum 对程序集的引用,也不知道对象类型。

所以我有以下设置:

dynamic thatObject = obtainThatObject();

我不能转换,因为我不知道对象类型(和枚举类型)。我应该如何查看Color

if( thatObject.Color.ToString() == "Red" ) {
    //blah
}

确实有效,但它看起来像是我在“The Daily WTF”中看到的最糟糕的货物崇拜代码示例。

如何正确进行检查?

【问题讨论】:

  • 你知道侧组件中枚举类型的所有可能值及其数值表示吗?
  • @YohDeadfall 我宁愿不依赖它——没人知道那里发生了什么变化。
  • 你对obtainThatObject()(及其返回类型)有影响吗?
  • @stefankmitph 不,我实现了一个回调,它的参数类型为object,我必须处理引用绑定的任何内容。
  • 如果枚举中不存在值“Red”,您是否希望例外?我认为这可能是最好的?

标签: c# .net dynamic enums late-binding


【解决方案1】:

在侧面组装中:

enum ColorEnum
{
    Red,
    Green,
    Blue
};

我们知道红色存在,但对其他颜色一无所知。所以我们只用已知值重新定义程序集中的枚举。

enum KnownColorEnum // in your assembly
{
    Red
};

因此我们可以进行解析:

public static KnownColorEnum? GetKnownColor(object value)
{
    KnownColorEnum color;

    if (value != null && Enum.TryParse<KnownColorEnum>(value.ToString(), out color))
    { return color; }

    return null;
}

例子:

// thatObject.Color == ColorEnum.Red
// or
// thatObject.Color == "Red"
if (GetKnowColor(thatObject.Color) == KnownColorEnum.Red) // true
{ }

// thatObject.Color == ColorEnum.Blue
if (GetKnowColor(thatObject.Color) == KnownColorEnum.Red) // false
{ }

【讨论】:

  • 这也使用了ToString()。这比只比较字符串文字有什么好处?
  • 更好的只是因为使用了类型。您不能使用整数表示,因为 ColorEnum 和基础值也可以更改。所以只有一种方法是使用字符串 coparison。
  • 是的,它使用TryParse() 并提取并行枚举。这就是区别吗?
  • 所有区别都在于强类型。字符串比较将比我的答案中的代码更快。但是,如果您多次使用一种颜色,最好选择存储在强类型变量中的并行枚举。
  • 是的,我明白你的意思。对于重用的情况,这确实更好。
【解决方案2】:

如何先将 Color 属性解析为您的枚举

if ((ColorEnum) Enum.Parse(typeof (ColorEnum), thatObject.Color.ToString()) == ColorEnum.Red)
{
    // do something
}

【讨论】:

  • 我没有对程序集的引用,否则我只会转换为 ColorEnum 并进行比较。
  • 但是你可以在你的程序集中重新定义枚举并使用它:)
  • @YohDeadfall 不,我不能,因为这将是两个不同的枚举。
  • 啊,是的 - 我忽略了关于参考的那部分
  • 如果thatObject.Color 包含未知值,则使用Enum.Parse() 将引发异常。应该使用Enum.TryParse&lt;T&gt;()
【解决方案3】:

一种可能的(非正统)方式是:强制您的动态对象(无论它是什么对象)成为 ExpandoObject(使用此扩展方法):

    public static dynamic ToDynamic(this object value)
    {
        IDictionary<string, object> expando = new ExpandoObject();

        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType()))
            expando.Add(property.Name, property.GetValue(value));

        return expando as ExpandoObject;
    }

转换你获取的对象:

var obtainedObject = (object)obtainThatObject();
var myexpando = obtainedObject.ToDynamic(); // now you have an ExpandoObject

这样您就可以在 IDictionary 中获取属性

IDictionary<string, object> dictionary= (IDictionary<string, object>) myexpando;
if(dictionary.ContainsKey("Color"))
{
    var myValue = dictionary["Color"];
    string color = myValue.ToString();
    if(color == "Green")
    {
         // blah
    }
}

这样你不必关心它是什么对象......

【讨论】:

猜你喜欢
  • 2011-02-16
  • 2022-01-20
  • 2020-12-31
  • 2010-12-20
  • 2018-02-06
  • 1970-01-01
相关资源
最近更新 更多