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

发布于 2024-12-02 15:35:20 字数 816 浏览 0 评论 0原文

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

具体来说,我想对返回 JsonResult 的 ASP.NET MVC 3 控制器操作进行单元测试。 JsonResult 具有 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}

Given an System.Object, how do I get a dynamic object with which to access any members it might have.

Specifically, I want to unit test an ASP.NET MVC 3 controller action which returns a JsonResult. The JsonResult has a Data property of type object. I'm populating this object with an anonymous type:

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

In my test, I want to do something like

var result = controller.Foo();

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

How is this done?

UPDATE
Though result.Data is of type object, inspecting it in the Watch window shows it has the following type:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

药祭#氼 2024-12-09 15:35:20

匿名类型是内部类型,编译器以尊重该保护的方式调用动态 api。使用 Nuget 中提供的开源 ImpromptuInterface,它具有 ImpromptuGet类将允许您包装匿名类型并使用动态 api,就好像来自匿名类型本身一样,这样您就不会遇到保护问题。

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

Anonymous types are internal, and the dynamic api's are called by the compiler in such a way to respect that protection. Using ImpromptuInterface, open source available in nuget, it has an ImpromptuGet class that will allow you to wrap your anonymous type and will use the dynamic api's as if from the anonymous type itself so you don't have the protection issue.

//using ImpromptuInterface.Dynamic
Assert.That(ImpromptuGet.Create(result.Data).Success, Is.EqualTo("Success"));
落花浅忆 2024-12-09 15:35:20

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

You can use an implementation of 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;
    }

}

and then:

    public void MyTest()
    {
        var json = new {Success = "Ok"};
        dynamic dynObj = new MyDynamic(json);
        Assert.AreEqual(dynObj.Success, "Ok");
    }
傲影 2024-12-09 15:35:20

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

Since you are trying to inspect an object which is Json, why not run result.Data through JsonValueProviderFactory, and then search the backing store for the key named "Success"?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文