【问题标题】:C# Set Property in unknown objectC# 在未知对象中设置属性
【发布时间】:2023-03-10 17:01:01
【问题描述】:

我必须在一个未知对象中设置一个属性。结构如下:

        ObjA.ObjB().ObjC.PropA = propValue;

ObjA 来自被引用的类。 ObjB() 是 object 类型,因此 ObjC 是未知的。我考虑过使用反射,但不知道在这种情况下如何正确使用它。

        object objB = ObjA.ObjB();
        Type objBType = objB.GetType();
        System.Reflection.XXXInfo objCInfo = objBType.GetXXX("ObjC");

        Type objCType = objCInfo.GetType();
        System.Reflection.PropertyInfo PropAInfo = objCType.GetProperty("PropA");
        PropAInfo.SetValue(PropAInfo, propValue, null);

答案(感谢 BigM):

        dynamic objAB = ObjA.ObjB(); 
        objAB.ObjC.PropA = propValue;

【问题讨论】:

  • 你不能重构它来创建一个通用的接口或基类吗?它将更易于维护和防故障。
  • objBType.GetProperty("ObjC");不工作?

标签: c# class object reflection gettype


【解决方案1】:

以下是一些通用扩展方法,可帮助您按名称获取和设置“未知”属性:

public static class ReflectionHelpers
{
    public static bool TrySetProperty<TValue>(this object obj, string propertyName, TValue value)
    {
        var property = obj.GetType()
            .GetProperties()
            .Where(p => p.CanWrite && p.PropertyType == typeof(TValue))
            .FirstOrDefault(p => p.Name == propertyName);

        if (property == null)
        {
            return false;
        }

        property.SetValue(obj, value);
        return true;
    }

    public static bool TryGetPropertyValue<TProperty>(this object obj, string propertyName, out TProperty value)
    {
        var property = obj.GetType()
            .GetProperties()
            .Where(p => p.CanRead && p.PropertyType == typeof(TProperty))
            .FirstOrDefault(p => p.Name == propertyName);

        if (property == null)
        {
            value = default(TProperty);
            return false;
        }

        value = (TProperty) property.GetValue(obj);
        return true;
    }
}

还有一个用法示例:

public class Program
{
    public static void Main()
    {
        var foo = new Foo
        {
            Bar = new Bar
            {
                HelloReflection = "Testing"
            }
        };

        string currentValue;
        if (foo.Bar.TryGetPropertyValue("HelloReflection", out currentValue))
        {
            Console.WriteLine(currentValue); // "Testing"
        }

        if (foo.Bar.TrySetProperty("HelloReflection", "123..."))
        {
            foo.Bar.TryGetPropertyValue("HelloReflection", out currentValue)

            Console.WriteLine(currentValue); // "123.."
        }
        else
        {
            Console.WriteLine("Failed to set value");
        }
    }
}

public class Foo
{
    public object Bar { get; set; }
}

public class Bar
{
    public string HelloReflection { get; set; }
}

【讨论】:

    【解决方案2】:

    这应该对你有用。

    object objB = ObjA.ObjB();
    Type objBType = objB.GetType();
    System.Reflection.PropertyInfo objCInfo = objBType.GetProperty("ObjC");
    object val = objCInfo.GetValue(objB);
    
    Type objCType = val.GetType();
    System.Reflection.PropertyInfo PropAInfo = objCType.GetProperty("PropA");
    PropAInfo.SetValue(val, propValue, null);
    

    但是,我认为可以在这里进行一些重新架构以使生活更轻松。例如,如果您对类型一无所知,那么您可以考虑使用dynamic 并从ObjCPropA 返回dynamic 类型 -但那里的性能受到影响。

    另一方面,如果有任何方法可以使用泛型,那会让你的生活变得更轻松。例如,此处设置属性值的代码,如果该方法是通用的,它可能能够定义 ObjC 的类型 - 但我无法用当前的 sn-p 推断出这一点。

    【讨论】:

    • 谢谢,动态工作。动态 objAB = ObjA.ObjB(); objAB.ObjC.PropA = propValue;
    • @SwissEngineer,很高兴能帮到你。如果这确实回答了您的问题,请不要忘记将其标记为答案。
    猜你喜欢
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多