c#-如何迭代类字段和设置属性
我不确定这是否可行,但我希望在不显式引用field对象的情况下迭代类并设置field member属性:c#-如何迭代类字段和设置属性,c#,class,properties,set,field,C#,Class,Properties,Set,Field,我不确定这是否可行,但我希望在不显式引用field对象的情况下迭代类并设置field member属性: public class Employee { public Person _person = new Person(); public void DynamicallySetPersonProperty() { MemberInfo[] members = this.GetType().GetMembers(); foreach (MemberInfo me
public class Employee
{
public Person _person = new Person();
public void DynamicallySetPersonProperty()
{
MemberInfo[] members = this.GetType().GetMembers();
foreach (MemberInfo member in members.Where(a => a.Name == "_person"))
//get the _person field
{
Type type = member.GetType();
PropertyInfo prop = type.GetProperty("Name"); //good, this works, now to set a value for it
//this line does not work - the error is "property set method not found"
prop.SetValue(member, "new name", null);
}
}
}
public class Person
{
public string Name { get; set; }
}
在我标记为您需要添加的答案中:
public static bool IsNullOrEmpty(this string source)
{
return (source == null || source.Length > 0) ? true : false;
}
您正在尝试设置Employee类的_person字段的Name属性。它没有。试试这个:
prop.SetValue(((FieldInfo)member).GetValue(this), "new name", null)
不确定是否需要像这样强制转换第一个参数:
prop.SetValue((Person)((FieldInfo)member).GetValue(this), "new name", null)
然后将其应用于_person字段的值。您试图对变量
member
的属性Name
执行SetValue()
,该属性是MemberInfo对象,并且该项目是只读的
注意:您不需要迭代所有memeber,也不需要使用反射获取字段\u person
,因为它与方法DynamicallySetPersonProperty()
在同一类中定义
所以代码应该是这样读的
PropertyInfo property = this._person.GetType().GetProperty("Name");
property.SetValue(this._person, "new name", null);
如果\u person
为空,则第一行将失败。因此,您可以使用reflectiopn获取字段的类型
FieldInfo field = this.GetType().GetField("_person", BindingFlags.Public);
PropertyInfo property = field.FieldType.GetProperty("Name");
但是现在,如果\u person
为空,访问此属性仍将失败
property.Setvalue(field.GetValue(this), "new name", null);
下面是一个完整的工作示例:
public class Person
{
public string Name { get; set; }
}
class Program
{
static void PropertySet(object p, string propName, object value)
{
Type t = p.GetType();
PropertyInfo info = t.GetProperty(propName);
if (info == null)
return;
if (!info.CanWrite)
return;
info.SetValue(p, value, null);
}
static void PropertySetLooping(object p, string propName, object value)
{
Type t = p.GetType();
foreach (PropertyInfo info in t.GetProperties())
{
if (info.Name == propName && info.CanWrite)
{
info.SetValue(p, value, null);
}
}
}
static void Main(string[] args)
{
Person p = new Person();
PropertySet(p, "Name", "Michael Ellis");
Console.WriteLine(p.Name);
PropertySetLooping(p, "Name", "Nigel Mellish");
Console.WriteLine(p.Name);
}
}
编辑:添加了一个循环变量,以便您可以查看如何循环属性信息对象。使用我创建的以下扩展方法,您可以设置或获取任何属性值,即使它们是嵌套的 GetPropertyValue(customObject,“Property.Nested.Child.Name”) 或设置 SetPropertyValue(customObject,“Property.Nested.Child.Name”,“我的自定义名称”) 希望您觉得它有用。试试这个:
public static void ApplyPropertyChanges(this object objDest, object objToCopyFrom)
{
if (objDest == null)
throw new ArgumentNullException();
if (objToCopyFrom == null)
throw new ArgumentNullException("objToCopyFrom");
if (objDest.GetType() != objToCopyFrom.GetType())
throw new Exception("Invalid type. Required: \"" + objDest.GetType().ToString() + "\"");
foreach (System.Reflection.PropertyInfo piOrig in objDest.GetType().GetProperties())
{
object editedVal = objToCopyFrom.GetType().GetProperty(piOrig.Name).GetValue(objToCopyFrom, null);
piOrig.SetValue(objDest,
editedVal,
null);
}
}
用法示例:
public ActionResult Edit(Team editedTeamData)
{
if (!ModelState.IsValid)
return View();
Team origTeam = (from t in _db.Teams
where t.TeamID == editedTeamData.TeamID
select t).FirstOrDefault();
origTeam.ApplyPropertyChanges(editedTeamData);
_db.SubmitChanges();
return RedirectToAction("Index");
}
我需要添加var p=person.GetType()。。。最后我从另一个班级给它打电话,但这不起作用。它应该是
GetProperty
而不是GetField
。非常好。。。尤其是筑巢。底座的示例更简单,但没有嵌套。另外,对于任何登陆这里的人(像我一样)必须深入了解“扩展”到底是什么,这是一个很好且简洁的解释:这失败了,因为您试图在memberinfo对象上设置属性名称。成员信息有名称,但不是[\u人]的名称。
[TestFixture]
public class ObjectExtensionsTest
{
private class MockClass
{
public MockClass()
{
Nested = new NestedMockClass();
}
public string Id { get; set; }
public string Name { get; set; }
public string GetOnly { get { return "MockClass"; } }
public string SetOnly { set { } }
public NestedMockClass Nested { get; set; }
}
private class NestedMockClass
{
public string NestedId { get; set; }
public string NestedName { get; set; }
public string NestedGetOnly { get { return "NestedMockClass"; } }
public string NestedSetOnly { set { } }
}
[Test]
public void TestShouldFindProperty()
{
MockClass mockObject = new MockClass();
Assert.IsTrue(mockObject.HasProperty("Id"));
Assert.IsTrue(mockObject.HasProperty("Name"));
Assert.IsTrue(mockObject.HasProperty("GetOnly"));
Assert.IsTrue(mockObject.HasProperty("SetOnly"));
Assert.IsTrue(mockObject.HasProperty("Nested"));
Assert.IsTrue(mockObject.HasProperty("Nested.NestedId"));
Assert.IsTrue(mockObject.HasProperty("Nested.NestedName"));
Assert.IsTrue(mockObject.HasProperty("Nested.NestedGetOnly"));
Assert.IsTrue(mockObject.HasProperty("Nested.NestedSetOnly"));
}
[Test]
public void TestShouldGetPropertyValue()
{
MockClass mockObject = new MockClass();
mockObject.Id = "1";
mockObject.Name = "Name";
mockObject.Nested.NestedId = "NestedId";
mockObject.Nested.NestedName = "NestedName";
Assert.AreEqual(mockObject.Id, mockObject.GetPropertyValue("Id"));
Assert.AreEqual(mockObject.Name, mockObject.GetPropertyValue("Name"));
Assert.AreEqual(mockObject.GetOnly, mockObject.GetPropertyValue("GetOnly"));
Assert.AreEqual(mockObject.Nested.NestedId, mockObject.GetPropertyValue("Nested.NestedId"));
Assert.AreEqual(mockObject.Nested.NestedName, mockObject.GetPropertyValue("Nested.NestedName"));
}
[Test]
public void TestShouldSetPropertyValue()
{
MockClass mockObject = new MockClass();
mockObject.SetPropertyValue("Id", "1");
mockObject.SetPropertyValue("Name", "Name");
mockObject.SetPropertyValue("Nested.NestedId", "NestedId");
mockObject.SetPropertyValue("Nested.NestedName", "NestedName");
Assert.AreEqual(mockObject.Id, "1");
Assert.AreEqual(mockObject.Name, "Name");
Assert.AreEqual(mockObject.Nested.NestedId, "NestedId");
Assert.AreEqual(mockObject.Nested.NestedName, "NestedName");
}
}
public static void ApplyPropertyChanges(this object objDest, object objToCopyFrom)
{
if (objDest == null)
throw new ArgumentNullException();
if (objToCopyFrom == null)
throw new ArgumentNullException("objToCopyFrom");
if (objDest.GetType() != objToCopyFrom.GetType())
throw new Exception("Invalid type. Required: \"" + objDest.GetType().ToString() + "\"");
foreach (System.Reflection.PropertyInfo piOrig in objDest.GetType().GetProperties())
{
object editedVal = objToCopyFrom.GetType().GetProperty(piOrig.Name).GetValue(objToCopyFrom, null);
piOrig.SetValue(objDest,
editedVal,
null);
}
}
public ActionResult Edit(Team editedTeamData)
{
if (!ModelState.IsValid)
return View();
Team origTeam = (from t in _db.Teams
where t.TeamID == editedTeamData.TeamID
select t).FirstOrDefault();
origTeam.ApplyPropertyChanges(editedTeamData);
_db.SubmitChanges();
return RedirectToAction("Index");
}