【问题标题】:Is there a way to set properties on struct instances using reflection?有没有办法使用反射在结构实例上设置属性?
【发布时间】:2011-06-08 14:35:41
【问题描述】:

我正在尝试编写一些代码来设置结构上的属性(重要的是它是结构上的属性)并且它失败了:

System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle();
PropertyInfo propertyInfo = typeof(System.Drawing.Rectangle).GetProperty("Height");
propertyInfo.SetValue(rectangle, 5, null);

高度值(由调试器报告)永远不会设置为任何值 - 它保持默认值 0。

我之前已经对课程进行了很多反思,并且效果很好。另外,我知道在处理结构时,如果设置字段,则需要使用 FieldInfo.SetValueDirect,但我不知道 PropertyInfo 的等效项。

【问题讨论】:

    标签: c# reflection propertyinfo


    【解决方案1】:

    rectangle 的值正在被装箱 - 但是你会丢失装箱的值,这是正在修改的内容。试试这个:

    Rectangle rectangle = new Rectangle();
    PropertyInfo propertyInfo = typeof(Rectangle).GetProperty("Height");
    object boxed = rectangle;
    propertyInfo.SetValue(boxed, 5, null);
    rectangle = (Rectangle) boxed;
    

    【讨论】:

    • 顺便说一句,这是可变值类型的危险之一的一个很好的例子。
    • 只要确保您没有在循环中执行此操作(或者性能不是问题),尤其是在结构很大的情况下。 :-)
    • +1 我遇到了完全相同的问题。 @Dan Bryant - 虽然我同意可变结构是邪恶的,但我这样做的原因是为不可变结构创建一个工厂类,并且我需要能够设置只读属性。我正在做一些类似于 MVC Model Binder 子系统所做的事情,虽然简单得多并且与 web 无关。所以我正在制作不可变的结构,但我只允许自己在创建时对它们进行一次变异,所以我认为这将避免所有潜在的邪恶。
    • 谁在使用 VB.net 应该使用以下示例: Dim _rectangle As New Rectangle() Dim _propertyInfo As PropertyInfo = GetType(Rectangle).GetProperty("Height") Dim boxed As ValueType = _rectangle _propertyInfo .SetValue(boxed, 5, Nothing) _rectangle = DirectCast(boxed, Rectangle)
    • @Sнаđошƒаӽ:不,值类型值不是对象,尽管继承层次结构。装箱正是分配对象以保存值类型值,然后获取对该对象的引用的过程。这里没有篇幅讨论值类型和引用类型之间的区别,但我强烈建议您研究它们。
    【解决方案2】:

    听说过SetValueDirect吗?他们成功是有原因的。 :)

    struct MyStruct { public int Field; }
    
    static class Program
    {
        static void Main()
        {
            var s = new MyStruct();
            s.GetType().GetField("Field").SetValueDirect(__makeref(s), 5);
            System.Console.WriteLine(s.Field); //Prints 5
        }
    }
    

    除了未记录的__makeref,您还可以使用其他方法(请参阅System.TypedReference),但它们更痛苦。

    【讨论】:

    • 请注意,“此 API 不符合 CLS。”.
    • __makeref() 未在 Unity3d 中使用 IL2CPP 实现
    • 不幸的是,除了不符合 CLS 之外,SetValueDirect 和 TypedReference 根本不适用于结构中的 readonly 字段。 SetValue 在这些条件下确实有效。
    • @EduardDumitru 我不确定SetValueDirect 的实现自从你写评论后是否发生了变化;但是,我刚刚用它修改了struct 上的public readonly 字段,并且成功了。
    • 如果您使用反射获取原始对象的问题,例如你不能打电话给__makeref GetValue...
    猜你喜欢
    • 2023-03-09
    • 2011-09-20
    • 1970-01-01
    • 2015-01-24
    • 2013-10-29
    • 1970-01-01
    • 2017-12-17
    • 2011-06-02
    相关资源
    最近更新 更多