2

给定一个System.Object,我如何获得一个动态对象来访问它可能拥有的任何成员。

具体来说,我想对返回JsonResult. JsonResult具有类型的Data属性object。我用匿名类型填充这个对象:

return Json(new { Success = "Success" });

在我的测试中,我想做类似的事情

var result = controller.Foo();

Assert.That(((SomeDynamicType)result.Data).Success, Is.EqualTo("Success"));

这是怎么做到的?

更新
虽然result.Data是 type object,但在 Watch 窗口中检查它显示它具有以下类型:

{
    Name = "<>f__AnonymousType6`1" 
    FullName = "<>f__AnonymousType6`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
} 
System.Type {System.RuntimeType}
4

3 回答 3

3

匿名类型是内部的,编译器以尊重该保护的方式调用动态 api。使用 nuget 中可用的开源 ImpromptuInterface,它有一个ImpromptuGet类,允许您包装匿名类型,并将使用动态 api,就像来自匿名类型本身一样,因此您没有保护问题。

//using ImpromptuInterface.Dynamic
Assert.That(ImpromptuGet.Create(result.Data).Success, Is.EqualTo("Success"));
于 2011-09-01T12:41:08.167 回答
1

您可以使用以下实现DynamicObject

public class MyDynamic: DynamicObject
{
    private readonly Dictionary<string, object> dictionary = new Dictionary<string, object>();

    public MyDynamic(object initialData)
    {
        if (initialData == null) throw new ArgumentNullException("initialData");
        var type = initialData.GetType();
        foreach (var propertyInfo in type.GetProperties())
        {
            dictionary.Add(propertyInfo.Name, propertyInfo.GetValue(initialData, null));
        }
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        dictionary.TryGetValue(binder.Name, out result);
        return true;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        dictionary[binder.Name] = value;
        return true;
    }

}

接着:

    public void MyTest()
    {
        var json = new {Success = "Ok"};
        dynamic dynObj = new MyDynamic(json);
        Assert.AreEqual(dynObj.Success, "Ok");
    }
于 2013-06-04T17:30:16.320 回答
-1

既然您正在尝试检查 Json 对象,为什么不通过 JsonValueProviderFactory 运行 result.Data,然后在后备存储中搜索名为“Success”的键?

于 2011-08-31T23:16:40.740 回答