我的情况很简单。在我的代码中,我有这样的代码:

dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();

//How to do this?
if (myVariable.MyProperty.Exists)   
//Do stuff

因此,基本上我的问题是如何检查(不抛出异常)某个属性在我的动态变量上是可用的。我可以使用GetType(),但我宁愿避免这样做,因为我并不真正需要知道对象的类型。我真正想知道的是是否有一个属性(或方法,如果这使工作更简单的话)可用。指针吗?


当前回答

我在单元测试中遇到过类似的问题。

使用SharpTestsEx可以检查属性是否存在。我使用这个测试我的控制器,因为JSON对象是动态的,有人可以更改名称,而忘记在javascript中更改它或其他东西,所以在编写控制器时测试所有属性应该增加我的安全性。

例子:

dynamic testedObject = new ExpandoObject();
testedObject.MyName = "I am a testing object";

现在,使用SharTestsEx:

Executing.This(delegate {var unused = testedObject.MyName; }).Should().NotThrow();
Executing.This(delegate {var unused = testedObject.NotExistingProperty; }).Should().Throw();

使用这个,我测试所有现有的属性使用“Should(). notthrow()”。

这可能离题了,但对某人来说可能有用。

其他回答

Denis的回答让我想到了另一个使用JsonObjects的解决方案,

头属性检查器:

Predicate<object> hasHeader = jsonObject =>
                                 ((JObject)jsonObject).OfType<JProperty>()
                                     .Any(prop => prop.Name == "header");

或许更好:

Predicate<object> hasHeader = jsonObject =>
                                 ((JObject)jsonObject).Property("header") != null;

例如:

dynamic json = JsonConvert.DeserializeObject(data);
string header = hasHeader(json) ? json.header : null;

如果你的用例是转换一个api响应,只携带一些字段,你可以使用这个:

var template = new { address = new { street = "" } };
var response = JsonConvert.DeserializeAnonymousType(await result.Content.ReadAsStringAsync(), template);

string street = response?.address?.street;

在我的例子中,我需要检查具有特定名称的方法是否存在,因此我使用了一个接口

var plugin = this.pluginFinder.GetPluginIfInstalled<IPlugin>(pluginName) as dynamic;
if (plugin != null && plugin is ICustomPluginAction)
{
    plugin.CustomPluginAction(action);
}

此外,接口可以包含的不仅仅是方法:

接口可以包含方法、属性、事件、索引器等等 这四种成员类型的组合。

来自:Interfaces (c#编程指南)

优雅,不需要陷阱异常或发挥反射…

以防它能帮到别人:

如果GetDataThatLooksVerySimilarButNotTheSame()方法返回一个ExpandoObject,你也可以在检查之前将其转换为dictionary。

dynamic test = new System.Dynamic.ExpandoObject();
test.foo = "bar";

if (((IDictionary<string, object>)test).ContainsKey("foo"))
{
    Console.WriteLine(test.foo);
}

也许使用反射?

dynamic myVar = GetDataThatLooksVerySimilarButNotTheSame();
Type typeOfDynamic = myVar.GetType();
bool exist = typeOfDynamic.GetProperties().Where(p => p.Name.Equals("PropertyName")).Any();