【问题标题】:How to set Vaues to the Nested Property using C# Reflection.?如何使用 C# 反射将值设置为嵌套属性。?
【发布时间】:2012-08-30 22:17:22
【问题描述】:

我正在尝试使用反射动态地为类的嵌套属性设置一个值。谁能帮我做这件事。

我正在上课Region,如下所示。

public class Region
{
    public int id;
    public string name;
    public Country CountryInfo;
}

public class Country
{
    public int id;
    public string name;
}

我有一个 Oracle 数据阅读器来提供来自 Ref 游标的值。

这会给我

Id,name,Country_id,Country_name

我可以通过下面将值分配给 Region.Id、Region.Name。

FieldName="id"
prop = objItem.GetType().GetProperty(FieldName, BindingFlags.Public | BindingFlags.Instance);
prop.SetValue(objItem, Utility.ToLong(reader_new[ResultName]), null);

对于嵌套属性,我可以通过读取字段名来创建一个实例来为下面的值赋值。

FieldName="CountryInfo.id"

if (FieldName.Contains('.'))
{
    Object NestedObject = objItem.GetType().GetProperty(Utility.Trim(FieldName.Split('.')[0]), BindingFlags.Public | BindingFlags.Instance);

    //getting the Type of NestedObject
    Type NestedObjectType = NestedObject.GetType();

    //Creating Instance
    Object Nested = Activator.CreateInstance(typeNew);

    //Getting the nested Property
    PropertyInfo nestedpropinfo = objItem.GetType().GetProperty(Utility.Trim(FieldName.Split('.')[0]), BindingFlags.Public | BindingFlags.Instance);

    PropertyInfo[] nestedpropertyInfoArray = nestedpropinfo.PropertyType.GetProperties();
    prop = nestedpropertyInfoArray.Where(p => p.Name == Utility.Trim(FieldName.Split('.')[1])).SingleOrDefault();

    prop.SetValue(Nested, Utility.ToLong(reader_new[ResultName]), null);
    Nestedprop = objItem.GetType().GetProperty(Utility.Trim(FieldName.Split('.')[0]), BindingFlags.Public | BindingFlags.Instance);

    Nestedprop.SetValue(objItem, Nested, null);
}

以上为Country.Id赋值。

但是由于我每次都在创建实例,因此如果我选择 Next Country.Name,我无法获得以前的 Country.Id 值。

谁能告诉可以为objItem(that is Region).Country.IdobjItem.Country.Name 赋值。这意味着如何为嵌套属性分配值,而不是每次都创建实例并分配。

提前致谢!

【问题讨论】:

标签: c# reflection propertyinfo


【解决方案1】:

您应该使用Country 属性调用PropertyInfo.GetValue 来获取国家/地区,然后使用Id 属性调用PropertyInfo.SetValue设置国家/地区的ID。

所以是这样的:

public void SetProperty(string compoundProperty, object target, object value)
{
    string[] bits = compoundProperty.Split('.');
    for (int i = 0; i < bits.Length - 1; i++)
    {
        PropertyInfo propertyToGet = target.GetType().GetProperty(bits[i]);
        target = propertyToGet.GetValue(target, null);
    }
    PropertyInfo propertyToSet = target.GetType().GetProperty(bits.Last());
    propertyToSet.SetValue(target, value, null);
}

【讨论】:

  • 为什么这被接受为答案,它会抛出一个 nullref,因为如果目标尚未实例化,GetValue() 将返回 null,这将导致进一步的异常。
  • 因为这不是教程。这个答案简短而甜蜜,只包含必要的代码。您有责任根据自己的要求添加检查/异常处理。顺便说一句,代码工作得很好。
  • 如果你想检查并实例化目标是否为空,你可以在这里获得完整的示例代码:stackoverflow.com/questions/51934180/…
【解决方案2】:

获取 Nest 属性,例如 Developer.Project.Name

private static System.Reflection.PropertyInfo GetProperty(object t, string PropertName)
            {
                if (t.GetType().GetProperties().Count(p => p.Name == PropertName.Split('.')[0]) == 0)
                    throw new ArgumentNullException(string.Format("Property {0}, is not exists in object {1}", PropertName, t.ToString()));
                if (PropertName.Split('.').Length == 1)
                    return t.GetType().GetProperty(PropertName);
                else
                    return GetProperty(t.GetType().GetProperty(PropertName.Split('.')[0]).GetValue(t, null), PropertName.Split('.')[1]);
            }

【讨论】:

  • 这个解决方案有一个重大缺陷,它不适用于通用列表。例如,您提供 FirstObject.MyList[0].MyValue 将简单地崩溃,因为它忽略了 [0] 第一个实例
猜你喜欢
  • 2018-07-19
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多