如何迭代类字段和设置属性

我不知道这是否可能,但我想遍历一个类,并设置一个字段成员属性,而不明确指出字段对象:

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; } 
 public class Person { public string Name { get; set; } } public class Employee { public Person person = new Person(); public void DynamicallySetPersonProperty() { var p = GetType().GetField("person").GetValue(this); p.GetType().GetProperty("Name").SetValue(p, "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); } } 

编辑:添加一个循环的变体,所以你可以看到如何通过属性信息对象循环。

使用我创build的以下扩展方法,即使嵌套,也​​可以设置或获取任何属性值

GetPropertyValue(customObject,“Property.Nested.Child.Name”);

或设置

SetPropertyValue(customObject,“Property.Nested.Child.Name”,“my custom name”);

  private class TargetProperty { public object Target { get; set; } public PropertyInfo Property { get; set; } public bool IsValid { get { return Target != null && Property != null; } } } private static TargetProperty GetTargetProperty(object source, string propertyName) { if (!propertyName.Contains(".")) return new TargetProperty { Target = source, Property = source.GetType().GetProperty(propertyName) }; string[] propertyPath = propertyName.Split('.'); var targetProperty = new TargetProperty(); targetProperty.Target = source; targetProperty.Property = source.GetType().GetProperty(propertyPath[0]); for (int propertyIndex = 1; propertyIndex < propertyPath.Length; propertyIndex++) { propertyName = propertyPath[propertyIndex]; if (!string.IsNullOrEmpty(propertyName)) { targetProperty.Target = targetProperty.Property.GetValue(targetProperty.Target, null); targetProperty.Property = targetProperty.Target.GetType().GetProperty(propertyName); } } return targetProperty; } public static bool HasProperty(this object source, string propertyName) { return GetTargetProperty(source, propertyName).Property != null; } public static object GetPropertyValue(this object source, string propertyName) { var targetProperty = GetTargetProperty(source, propertyName); if (targetProperty.IsValid) { return targetProperty.Property.GetValue(targetProperty.Target, null); } return null; } public static void SetPropertyValue(this object source, string propertyName, object value) { var targetProperty = GetTargetProperty(source, propertyName); if(targetProperty.IsValid) { targetProperty.Property.SetValue(targetProperty.Target, value, null); } } 

这里有几个testing

  [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"); } } 

希望你觉得它有用。

您正尝试设置Employee类的_person字段的Name属性。 它没有一个。 尝试这个:

 prop.SetValue(((FieldInfo)member).GetValue(this), "new name", null) 

不知道是否需要像这样投下第一个参数:

 prop.SetValue((Person)((FieldInfo)member).GetValue(this), "new name", null) 

然后将其应用于_person字段的值。

您尝试对MemberInfo对象的variablesmember的属性Name执行SetValue() ,并且此proeprty是只读的。

注意,你不需要迭代所有的记忆,你不需要获得字段_person的reflection,因为它是在与DynamicallySetPersonProperty()方法相同的类中定义的。

所以代码如下所示。

 PropertyInfo property = this._person.GetType().GetProperty("Name"); property.SetValue(this._person, "new name", null); 

如果_person为null,则第一行将失败。 所以你可以使用reflectiopn来获取字段的types。

 FieldInfo field = this.GetType().GetField("_person", BindingFlags.Public); PropertyInfo property = field.FieldType.GetProperty("Name"); 

但是,如果_person为null,则现在访问此属性将仍然失败。

 property.Setvalue(field.GetValue(this), "new name", null); 

尝试这个:

 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"); } 

看看这个CodeProject有关你正在做什么的文章

http://www.codeproject.com/KB/cs/fast_dynamic_properties.aspx