如何将一个对象包装在一个动态对象中

本文关键字:一个 动态 对象 一个对象 包装 | 更新日期: 2023-09-27 18:07:07

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

具体来说,我想对ASP进行单元测试。. NET MVC 3控制器动作,它返回一个JsonResultJsonResult具有object型的Data性质。我用匿名类型填充这个对象:

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

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

的事情
var result = controller.Foo();
Assert.That(((SomeDynamicType)result.Data).Success, Is.EqualTo("Success"));

这是怎么做的?


虽然result.Data的类型是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}

如何将一个对象包装在一个动态对象中

匿名类型是内部的,编译器调用动态api的方式尊重这种保护。使用ImpromptuInterface, nuget中提供的开源,它有一个ImpromptuGet类,允许你包装你的匿名类型,并将使用动态api,就像从匿名类型本身,所以你没有保护问题。

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

您可以使用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");
    }

既然你试图检查一个对象是Json,为什么不运行结果。数据通过JsonValueProviderFactory,然后搜索后备存储的关键名称为"成功"?