C# 使用反射查找和更新基于类型的对象

C# 使用反射查找和更新基于类型的对象,c#,reflection,C#,Reflection,我试图检查嵌套对象中的值,并在必要时替换它们。使用反射,我可以遍历所有嵌套对象并获取属性类型,但我无法检索值并替换值。我举了一个简单的例子 假设我有以下模型: public class Employee { #region Members private string _FirstName; private string _LastName; private StreetAddress _EmployeeAddress; #endregion #r

我试图检查嵌套对象中的值,并在必要时替换它们。使用反射,我可以遍历所有嵌套对象并获取属性类型,但我无法检索值并替换值。我举了一个简单的例子

假设我有以下模型:

public class Employee
{
    #region Members
    private string _FirstName;
    private string _LastName;
    private StreetAddress _EmployeeAddress;
    #endregion
    #region Properties
    public string FirstName { get { return _FirstName; } set { value = _FirstName; } }
    public string LastName { get { return _LastName; } set { value = _LastName; } }
    public StreetAddress EmployeeAddress { get { return _EmployeeAddress; } set { value = _EmployeeAddress; } }
    #endregion
}

public class StreetAddress
{
    #region Members
    private string _Street;
    private string _City;
    private string _State;
    private string _Zip;
    #endregion
    #region Properties
    public string Street { get { return _Street; } set { value = _Street; } }
    public string City { get { return _City; } set { value = _City; } }
    public string State { get { return _State; } set { value = _State; } }
    public string Zip { get { return _Zip; } set { value = _Zip; } }
    #endregion
}
在我的场景中,我需要将StreetAddress中出现的任何对象的StreetAddress从“123 Main Street”更新为“999 Main Street”。StreetAddress对象可以出现在任何给定对象的任何级别。 假设我将Employee强制转换为一个对象,我使用下面的代码遍历Employee对象,查找StreetAddress类型

用法:

ReadPropertiesRecursive2(Employee.GetType());

我不确定在使用1返回值和2更新值(如果需要)的语法中缺少了什么。如果你能给我指出正确的方向,那就太棒了,或者如果有更好的方法,我很想知道。提前谢谢

最大的问题是GetValue需要一个实际对象来获取的值。PropertyInfo,就这一点而言,类型只是元数据。换句话说,GetValue的有效使用如下所示:

Employee emp = new Employee();
PropertyInfo addressProp = typeof(Employee).GetProperty("StreetAddress");
string address = addressProp.GetValue(emp);
传递null将尝试使其脱离静态实例,以获取其价值


重构您的代码以获得并抵消实际实例的影响,您应该不会有问题。

您这里的问题是您正在输入一种类型的对象,而不是对象本身

当您将参数提供为

ReadPropertiesRecursive2(Employee.GetType());
您不是提供Employee对象本身,而是提供对象的“类型”。 因此,当您要求它读取这些属性的值时,它会说“读取哪个对象上的属性或字段?”

StreetAddressType.GetProperty("Street").GetValue(StreetAddressType, null);
上面的null必须是您正在处理的实际对象。 将方法签名更改为:

private static void ReadPropertiesRecursive2(Type type, object obj)
然后将保存数据的实际对象作为第二个参数输入

然后,您可能能够执行以下操作:

StreetAddressType.GetProperty("Street").GetValue(StreetAddressType, obj);
现在,您将告诉它读取obj对象上的“Street”字段

如果你能给我指出正确的方向,那就太棒了,或者如果有更好的方法,我很想知道

这个答案更多地属于“指向正确的方向”类别

您似乎希望更新各种实体上的街道地址,这些实体可能在其结构中的某个位置包含StreetAddress实例,可能嵌套了几层

这方面的基本问题是,我们的代码应该编写为与特定类的特定属性交互。我们需要知道要更新哪个属性并更新该属性,而不仅仅是更新任何看起来可能是正确的属性,因为它属于某种类型

考虑这个例子:

public class Employee
{
    public StreetAddress Address {get;set;}
    public EmergencyContact EmergencyContact {get;set;}
}

public class EmergencyContact
{
    public StreetAddress Address {get;set;}
}
如果以正常方式更新地址:

employee.StreetAddress = updatedAddress;

那你就没事了

但如果你这样做:

UpdateStreetAddress(object something, "123 Maple St.")
…然后它会查找每个StreetAddress,它会更新该对象中任何位置的每个StreetAddress。它将设置员工的地址和员工的紧急联系人地址


尝试编写一个适用于所有类的一刀切方法是不值得的。最好只编写代码来准确地更新您需要更新的内容。如果代码多一点也没关系,尽管可能不会。你可以通过不处理缺陷、意外的副作用和未来的开发人员不必弄清楚发生了什么来挽回时间。

担心这是一个问题,我可以问你为什么需要使用反射来做这件事吗?同意-除非这只是一个了解反射如何工作的实验,几乎可以肯定的是,最好不要使用反射。当你以正常的方式使用你的属性和方法时,当你试图做错事时,你会得到一个编译器错误。这很好,因为它很容易修复。使用反射,您将得到一个运行时错误,因为在程序运行之前,它无法判断什么将工作或什么将不工作。反射在我们需要的时候就在那里,但它不应该是我们在正常情况下使用类的方式。谢谢大家的反馈。似乎我正试图用一个通用解决方案解决一些具体问题,我应该采取更安全、更强类型的路线。我选择反射的原因是当时我的对象类型未知。我感谢大家的意见。
employee.EmergencyContact.StreetAddress = updatedAddress;
UpdateStreetAddress(object something, "123 Maple St.")