首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在C#中迭代匿名对象的属性?

如何在C#中迭代匿名对象的属性?
EN

Stack Overflow用户
提问于 2010-04-08 01:23:39
回答 6查看 34.7K关注 0票数 63

我想将匿名对象作为方法的参数,然后遍历其属性以将每个属性/值添加到动态ExpandoObject中。

所以我需要的是从

new { Prop1 = "first value", Prop2 = SomeObjectInstance, Prop3 = 1234 }

要知道每个属性的名称和值,并能够将它们添加到ExpandoObject中。

我该如何做到这一点?

附注:这将在我的许多单元测试中完成(我正在使用它来重构设置中的许多垃圾),因此性能在某种程度上是相关的。我对反射的了解还不够多,但据我所知,它的性能相当重,所以如果可能的话,我宁愿避免它……

后续问题:正如我所说的,我将这个匿名对象作为一个方法的参数。我应该在方法的签名中使用什么数据类型?如果我使用object,是否所有属性都可用

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-04-08 01:26:40

foreach(var prop in myVar.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
   Console.WriteLine("Name: {0}, Value: {1}",prop.Name, prop.GetValue(myVar,null));
}
票数 85
EN

Stack Overflow用户

发布于 2013-07-24 08:08:45

考虑匿名对象以获得它的属性名称和值,然后利用ExpandoObject实际上是一个字典来填充它。下面是一个表示为单元测试的示例:

    [TestMethod]
    public void ShouldBeAbleToConvertAnAnonymousObjectToAnExpandoObject()
    {
        var additionalViewData = new {id = "myControlId", css = "hide well"};
        dynamic result = new ExpandoObject();
        var dict = (IDictionary<string, object>)result;
        foreach (PropertyInfo propertyInfo in additionalViewData.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
        {
            dict[propertyInfo.Name] = propertyInfo.GetValue(additionalViewData, null);
        }
        Assert.AreEqual(result.id, "myControlId");
        Assert.AreEqual(result.css, "hide well");
    }
票数 9
EN

Stack Overflow用户

发布于 2010-04-08 01:48:55

另一种方法是使用DynamicObject而不是ExpandoObject,这样当您实际尝试从另一个对象访问属性时,才会有进行反射的开销。

public class DynamicForwarder : DynamicObject 
{
    private object _target;

    public DynamicForwarder(object target)
    {
        _target = target;
    }

    public override bool TryGetMember(
        GetMemberBinder binder, out object result)
    {
        var prop = _target.GetType().GetProperty(binder.Name);
        if (prop == null)
        {
            result = null;
            return false;
        }

        result = prop.GetValue(_target, null);
        return true;
    }
}

现在,只有当您实际尝试通过动态get访问属性时,它才会进行反射。缺点是,如果您重复访问相同的属性,它每次都必须进行反射。因此,您可以缓存结果:

public class DynamicForwarder : DynamicObject 
{
    private object _target;
    private Dictionary<string, object> _cache = new Dictionary<string, object>();

    public DynamicForwarder(object target)
    {
        _target = target;
    }

    public override bool TryGetMember(
        GetMemberBinder binder, out object result)
    {
        // check the cache first
        if (_cache.TryGetValue(binder.Name, out result))
            return true;

        var prop = _target.GetType().GetProperty(binder.Name);
        if (prop == null)
        {
            result = null;
            return false;
        }

        result = prop.GetValue(_target, null);
        _cache.Add(binder.Name, result); // <-------- insert into cache
        return true;
    }
}

您可以支持存储目标对象列表以合并它们的属性,并支持设置属性(使用名为TrySetMember的类似覆盖来允许您在缓存字典中动态设置值)。

当然,反射的开销可能不值得担心,但对于大型对象,这可能会限制它的影响。也许更有趣的是它给了你额外的灵活性。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2594527

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档