非反射方式来设置编译时已知类型的属性

发布于 2025-01-30 02:31:57 字数 1336 浏览 2 评论 0原文

我正在研究一个项目,该项目要求用户能够在某些类型列表中修改对象的属性,该类型已知在编译时已知。

例如,假设我有一种按

public class A
{
   public float foo;
}

在运行时以接近本地速度进行反射的属性定义的类型(项目必不可少),我使用了一个C#脚本,该脚本使用反射通过属性枚举列举的代码,以生成看起来像类似的代码然后将其编译。

public void Set(A obj, string path, object value)
{
    switch (path)
    {
        case "foo":
            obj.foo = (float)value;
            break;
    }
}

这对于简单类型来说很好,但是对于更复杂的类型,特别是在结构属性是其成员的情况下,它变得更加困难。

public class B
{
    public C foo { get; set; }
}
public struct C
{
    public float bar;
}

该系统生成的代码不再有效,因为访问结构属性会创建副本。

public void Set(B obj, string path, object value)
{
    switch (path)
    {
        //...
        case "foo.bar":
            // Cannot modify the return value of 'C.bar' because it is not a variable
            obj.foo.bar = (float)value;
            break;
    }
}

现在,我能做的就是修改系统以创建临时结构变量,修改我要访问的成员,然后将属性的值设置为temp变量。

public void Set(B obj, string path, object value)
{
    switch (path)
    {
        //...
        case "foo.bar":
            C tmp = obj.foo;
            tmp.bar = (float)value;
            obj.foo = tmp;
            break;
    }
}

该系统有几个问题。嵌套的结构属性将是地狱,我必须检查每个父属性属性以确保存在设置器方法。这似乎不必要且繁琐,但我没有其他选择。

有没有办法可以从字符串路径中为对象设置属性值而无需运行时反射?

I am working on a project that requires a user to be able to modify properties of an object within a certain list of types, known at compile time.

For example, say I have a type defined by

public class A
{
   public float foo;
}

To set properties without reflection at near-native speeds during runtime (which is necessary for the project), I used a C# script which enumerates through the properties using reflection to generate code that looks something like this, which is then compiled.

public void Set(A obj, string path, object value)
{
    switch (path)
    {
        case "foo":
            obj.foo = (float)value;
            break;
    }
}

This works fine for simple types, but for more complex types, specifically where struct properties are its members, it becomes more difficult.

public class B
{
    public C foo { get; set; }
}
public struct C
{
    public float bar;
}

The code generated by this system no longer works, because accessing the struct property creates a copy.

public void Set(B obj, string path, object value)
{
    switch (path)
    {
        //...
        case "foo.bar":
            // Cannot modify the return value of 'C.bar' because it is not a variable
            obj.foo.bar = (float)value;
            break;
    }
}

Now, what I can do is modify the system to create a temporary struct variable, modify the member I want to access, and set the property's value to the temp variable, like so.

public void Set(B obj, string path, object value)
{
    switch (path)
    {
        //...
        case "foo.bar":
            C tmp = obj.foo;
            tmp.bar = (float)value;
            obj.foo = tmp;
            break;
    }
}

This system has several problems though. Nested struct properties would be hell to unwrap, and I would have to check every single parent property to ensure a setter method exists. This seems unnecessary and cumbersome, but I don't see any other option.

Is there a way that I can set property values for an object from a string path without runtime reflection?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文