【问题标题】:How to set nested property value using FastMember如何使用 FastMember 设置嵌套属性值
【发布时间】:2017-07-16 04:23:58
【问题描述】:

当我尝试使用 FastMember 设置嵌套成员属性时出现异常。例如当有这些类时

public class A
{
    public B First { get; set; }
}

public class B
{
    public string Second { get; set; }
}

我想将实例的First.Second 设置为"hello"

var b = new B{ Second = "some value here" };
var a = new A{ First = b };
var accessor = ObjectAccessor.Create(a);
accessor["First.Second"] = value; // this does not work and gives ArgumentOutOfRangeException

我无法将其拆分为 ["First"]["Second"],因为此时我不知道深度。嵌套属性是否有神奇的访问方式,还是我必须自己拆分层次结构?

【问题讨论】:

    标签: c# reflection fastmember nested-properties


    【解决方案1】:

    我以这种方式使用扩展方法递归地解决了这个问题:

    public static class FastMemberExtensions
    {
        public static void AssignValueToProperty(this ObjectAccessor accessor, string propertyName, object value)
        {
            var index = propertyName.IndexOf('.');
    
            if (index == -1)
            {
                accessor[propertyName] = value;
            }
            else
            {
                accessor = ObjectAccessor.Create(accessor[propertyName.Substring(0, index)]);
                AssignValueToProperty(accessor, propertyName.Substring(index + 1), value);
            }
        }        
    }
    

    ...开始如下:

    ObjectAccessor.Create(a).AssignValueToProperty("First.Second", "hello")
    

    【讨论】:

    【解决方案2】:

    您需要使用多个 ObjectAccessor 实例来遍历对象图。

    public static void UseFastMember()
    {
        var b = new B { Second = "some value here" };
        var a = new A { First = b };
        var value = "hello";
        var a_accessor = ObjectAccessor.Create(a);
        var first = a_accessor["First"];
        var b_accessor = ObjectAccessor.Create(first);
        b_accessor["Second"] = value;
    }
    

    【讨论】:

    • 感谢您提供的信息,我认为可能已经有内置解决方案。我发布了我现在使用的递归函数。任何想法如何解决可空类型的问题?这是这里的问题:stackoverflow.com/questions/40306591/…
    【解决方案3】:

    向@Beachwalker 致敬以获得灵感。但是如果您使用TypeAccessor 而不是ObjectAccessor,这是一种我已经取得很大成功的扩展方法:

    public static class TypeAccessorExtensions
    {
        public static void AssignValue<T>(this TypeAccessor accessor, T t, MemberSet members, string fieldName, object fieldValue)
        {
            var index = fieldName.IndexOf('.');
    
            if (index == -1)
            {
                if (members.Any(m => string.Equals(m.Name, fieldName, StringComparison.OrdinalIgnoreCase)))
                    accessor[t, fieldName] = fieldValue;
            }
            else
            {
                string fieldNameNested = fieldName.Substring(0, index);
                var member = members.FirstOrDefault(m => string.Equals(m.Name, fieldNameNested, StringComparison.OrdinalIgnoreCase));
    
                if (member != null)
                {
                    var nestedAccesor = TypeAccessor.Create(member.Type);
                    var tNested = accessor[t, fieldNameNested];
    
                    if (tNested == null)
                    {
                        tNested = Activator.CreateInstance(member.Type);
                        accessor[t, fieldNameNested] = tNested;
                    }
    
                    nestedAccesor.AssignValue(tNested, nestedAccesor.GetMembers(), fieldName.Substring(index + 1), fieldValue);
                }
    
            }
        }
    }
    

    【讨论】:

    • 是我也问了这个问题,因为当时没有人回答我自己解决了这个问题。不过,谢谢你的帽子。 ;-)
    • 呵呵,看到了!喜欢“自我加入”(哇,那太蹩脚了)——无论哪种方式都很棒!
    猜你喜欢
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    • 2018-07-19
    • 2010-10-24
    相关资源
    最近更新 更多