如何在动态对象中包装对象?

时间:2011-08-31 21:37:41

标签: c# unit-testing asp.net-mvc-3 dynamic expandoobject

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

具体来说,我想对一个返回JsonResult的ASP.NET MVC 3控制器动作进行单元测试。 JsonResult的{​​{1}}属性类型为Data。我用匿名类型填充此对象:

object

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

的事情
return Json(new { Success = "Success" });

这是怎么做到的?

更新
虽然var result = controller.Foo(); Assert.That(((SomeDynamicType)result.Data).Success, Is.EqualTo("Success")); 的类型为result.Data,但在“监视”窗口中检查它会显示它具有以下类型:

object

3 个答案:

答案 0 :(得分:3)

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

//using ImpromptuInterface.Dynamic
Assert.That(ImpromptuGet.Create(result.Data).Success, Is.EqualTo("Success"));

答案 1 :(得分: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");
    }

答案 2 :(得分:-1)

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