如何使用 FastMember 设置嵌套的 属性 值
How to set nested property value using FastMember
当我尝试使用 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"],因为此时我不知道深度。嵌套属性是否有神奇的访问权限,还是我必须自己拆分层次结构?
您需要使用多个 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;
}
我使用扩展方法递归地解决了这个问题:
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")
向@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);
}
}
}
}
当我尝试使用 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"],因为此时我不知道深度。嵌套属性是否有神奇的访问权限,还是我必须自己拆分层次结构?
您需要使用多个 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;
}
我使用扩展方法递归地解决了这个问题:
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")
向@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);
}
}
}
}