首页 / C# / c#-使用反射在嵌套对象中设置属性
c#-使用反射在嵌套对象中设置属性
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c#-使用反射在嵌套对象中设置属性,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6451字,纯文字阅读大概需要10分钟。
内容图文
![c#-使用反射在嵌套对象中设置属性](/upload/InfoBanner/zyjiaocheng/668/f6dede201ede42de8c01eaf20644fac6.jpg)
我正在尝试使用反射在obj1中设置Address1,但我不知道如何获得对正确对象的引用.我不确定如何获取对Address1实例的引用以传递到SetValue()的第一个参数中
第1轮:
public class StackOverflowReflectionTest
{
[Fact]
public void SetDeepPropertyUsingReflection()
{
var breadCrumb = ".Addresses[0].Address1";
var obj1 = new Person()
{
Name = "Eric",
Addresses = new List<Address>()
{
new Address() {Address1 = "123 First Street"}
}
};
var newAddress1 = "123 Second Street";
var propNames = breadCrumb.Split(".");
for (var index = 0; index < propNames.Length; index++)
{
var propName = propNames[index];
if (propName.Contains("["))
{
var propNameToGet = propName.Substring(0, propName.IndexOf("[", StringComparison.Ordinal));
var prop = obj1.GetType().GetProperty(propNameToGet);
var leftBrace = propName.IndexOf("[", StringComparison.Ordinal);
var rightBrace = propName.IndexOf("]", StringComparison.Ordinal);
var position = int.Parse(propName.Substring(leftBrace + 1, rightBrace - leftBrace - 1));
var propNameToSet = propNames[index + 1];
var propToSet = prop.PropertyType.GetGenericArguments()[position].GetProperty(propNameToSet);
propToSet.SetValue(obj1, newAddress1);
}
else
{
//TODO: deal with different types
}
}
}
public class Person
{
public string Name { get; set; }
public IList<Address> Addresses { get; set; }
}
public class Address
{
public string Address1 { get; set; }
}
}
第二轮基于Ed的反馈,仍然停留在如何获取此行的值上:var value = property.GetValue(obj,new object [] {indexPart});
public class StackOverflowReflectionTest
{
[Fact]
public void SetDeepPropertyUsingReflectionRound2()
{
var breadCrumb = "Addresses[0].Address1";
var obj1 = new Person()
{
Name = "Eric",
Addresses = new List<Address>()
{
new Address() {Address1 = "123 First Street"}
}
};
var newAddress1 = "123 Second Street";
SetPropertyValueByPath(obj1, breadCrumb, newAddress1);
}
public bool CrackPropertyName(string name, out string namePart, out object indexPart)
{
if (name.Contains("["))
{
namePart = name.Substring(0, name.IndexOf("[", StringComparison.Ordinal));
var leftBrace = name.IndexOf("[", StringComparison.Ordinal);
var rightBrace = name.IndexOf("]", StringComparison.Ordinal);
indexPart = name.Substring(leftBrace + 1, rightBrace - leftBrace - 1);
return true;
}
else
{
namePart = name;
indexPart = null;
return false;
}
}
public object GetPropertyValue(object obj, string name)
{
if(CrackPropertyName(name, out var namePart, out var indexPart))
{
var property = obj.GetType().GetProperty(namePart);
var value = property.GetValue(obj, new object[] { indexPart });
return value;
}
else
{
return obj.GetType().GetProperty(name);
}
}
public void SetPropertyValue(object obj, string name, object newValue)
{
var property = typeof(Address).GetProperty(name);
property.SetValue(obj, newValue);
}
public void SetPropertyValueByPath(object obj, string path, object newValue)
{
var pathSegments = path.Split(".");
if (pathSegments.Length == 1)
{
SetPropertyValue(obj, pathSegments[0], newValue);
}
else
{
//// If more than one remaining segment, recurse
var child = GetPropertyValue(obj, pathSegments[0]);
SetPropertyValueByPath(child, String.Join(".", pathSegments.Skip(1)), newValue);
}
}
public class Person
{
public string Name { get; set; }
public IList<Address> Addresses { get; set; }
}
public class Address
{
public string Address1 { get; set; }
}
}
解:
public class StackOverflowReflectionTest
{
[Fact]
public void SetDeepPropertyUsingReflectionSolution()
{
var breadCrumb = "Addresses[0].Address1";
var obj1 = new Person()
{
Name = "Eric",
Addresses = new List<Address>()
{
new Address() {Address1 = "123 First Street"}
}
};
var newAddress1 = "123 Second Street";
SetPropertyValueByPath(obj1, breadCrumb, newAddress1);
}
public bool CrackPropertyName(string name, out string namePart, out object indexPart)
{
if (name.Contains("["))
{
namePart = name.Substring(0, name.IndexOf("[", StringComparison.Ordinal));
var leftBrace = name.IndexOf("[", StringComparison.Ordinal);
var rightBrace = name.IndexOf("]", StringComparison.Ordinal);
indexPart = name.Substring(leftBrace + 1, rightBrace - leftBrace - 1);
return true;
}
else
{
namePart = name;
indexPart = null;
return false;
}
}
public object GetPropertyValue(object obj, string name)
{
if(CrackPropertyName(name, out var namePart, out var indexPart))
{
var property = obj.GetType().GetProperty(namePart);
var list = property.GetValue(obj);
var value = list.GetType().GetProperty("Item").GetValue(list, new object[] { int.Parse(indexPart.ToString()) });
return value;
}
else
{
return obj.GetType().GetProperty(namePart);
}
}
public void SetPropertyValue(object obj, string name, object newValue)
{
var property = typeof(Address).GetProperty(name);
property.SetValue(obj, newValue);
}
public void SetPropertyValueByPath(object obj, string path, object newValue)
{
var pathSegments = path.Split(".");
if (pathSegments.Length == 1)
{
SetPropertyValue(obj, pathSegments[0], newValue);
}
else
{
//// If more than one remaining segment, recurse
var child = GetPropertyValue(obj, pathSegments[0]);
SetPropertyValueByPath(child, String.Join(".", pathSegments.Skip(1)), newValue);
}
}
public class Person
{
public string Name { get; set; }
public IList<Address> Addresses { get; set; }
}
public class Address
{
public string Address1 { get; set; }
}
}
解决方法:
Type.GetGenericArguments()并没有像我想的那样做.
您想要的是递归.给定“ Foo.Bar [1] .Baz”,得到Foo.从中获得Bar [1].从其父级的Baz获取PropertyInfo,使用它来设置Foo的Bar [1]属性的Baz属性的值.
分解:
>编写一种“破解”属性名称并使用参数返回名称部分和索引值部分的方法:“ IndexedProperty [1]”进入;出现“ IndexedProperty”和整数1.进入“ FooBar”,出现“ FooBar”,并且为空.如果有索引器,则返回true,否则返回false.
bool CrackPropertyName(string name, out string namePart, out object indexPart)
>编写一个采用对象的方法,并使用字符串“ PropertyName”或“ IndexedPropety [0]”(不是路径-无点),然后在该对象上返回该属性的值.它使用CrackPropertyName()简化其工作.
object GetPropertyValue(object obj, string name)
>编写一种通过名称(而不是路径,仅通过名称)设置属性值的方法.同样,它使用CrackPropertyName()简化其工作.
void SetPropertyValue(object obj, string name, object newValue)
>使用上述方法的递归方法:
void SetPropertyValueByPath(object obj, string path, object newvalue)
{
var pathSegments = /* split path on '.' */;
if (pathSegments.Length == 1)
{
SetPropertyValue(obj, pathSegments[0], newValue);
}
else
{
// If more than one remaining segment, recurse
var child = GetNamedPropertyvalue(obj, pathSegments[0]);
return SetPropertyValueByPath(obj, String.Join(".", pathSegments.Skip(1)), newValue);
}
}
这些方法都很简单.由于无论如何都在使用反射,因此您也可以全力以赴,编写一个设置任何属性的非泛型方法.
内容总结
以上是互联网集市为您收集整理的c#-使用反射在嵌套对象中设置属性全部内容,希望文章能够帮你解决c#-使用反射在嵌套对象中设置属性所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。