You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在公共静态类中自动获取私有内部类的公共属性?

解决方案

根据你的场景限制(Bar必须是仅含公共字段的空类、不能暴露Bar类、避免手动编写大量Get方法),以下几种方案可以解决问题:

方案1:反射动态获取字段值

通过反射自动读取Bar的公共字段,无需为每个字段编写单独的Get方法,新增字段后直接通过字段名调用即可。

public static class Foo
{
    private class Bar
    {
        public float x;
        public float y;
        public float z;
        // 新增字段直接添加在这里
    }

    private static readonly Bar _bar = new Bar();

    // 泛型方法获取指定字段值
    public static T GetField<T>(string fieldName)
    {
        var field = typeof(Bar).GetField(fieldName);
        if (field == null)
            throw new ArgumentException($"不存在名为{fieldName}的字段");
        return (T)field.GetValue(_bar);
    }

    // 可选:一次性获取所有字段的键值对
    public static Dictionary<string, object> GetAllFields()
    {
        var fields = typeof(Bar).GetFields();
        var fieldValues = new Dictionary<string, object>();
        foreach (var field in fields)
        {
            fieldValues[field.Name] = field.GetValue(_bar);
        }
        return fieldValues;
    }
}

调用示例:

// 获取单个字段
float xValue = Foo.GetField<float>("x");
// 获取所有字段
var allValues = Foo.GetAllFields();
float zValue = (float)allValues["z"];

优缺点:无需手动维护方法,新增字段零成本;但需要硬编码字段名(拼写错误会在运行时暴露),反射有轻微性能开销(非高频调用可忽略)。

方案2:利用dynamic类型(谨慎使用)

返回dynamic类型绕过编译时类型检查,直接访问Bar的字段,语法最简洁,但牺牲了编译时校验。

public static class Foo
{
    private class Bar
    {
        public float x;
        public float y;
        public float z;
        // 新增字段直接添加
    }

    private static readonly Bar _bar = new Bar();

    public static dynamic GetBarInstance()
    {
        return _bar;
    }
}

调用示例:

float yValue = Foo.GetBarInstance().y;

优缺点:使用最方便,新增字段直接访问;但无编译时检查,拼写错误会导致运行时异常,且dynamic在Unity中频繁调用会有性能损耗,适合非核心逻辑场景。

方案3:自动生成Get方法(性能最优)

通过Unity Editor工具或Roslyn生成器,自动为Bar的所有字段生成对应的Get方法,兼顾编译时校验和性能,新增字段只需运行生成器即可。

Unity Editor生成脚本示例

using UnityEditor;
using System.IO;
using System.Reflection;
using System.Text;

public class FooGetterGenerator : EditorWindow
{
    [MenuItem("Tools/生成Foo字段Get方法")]
    public static void OpenGenerator()
    {
        GetWindow<FooGetterGenerator>("生成Get方法");
    }

    private void OnGUI()
    {
        if (GUILayout.Button("一键生成"))
        {
            GenerateGetMethods();
        }
    }

    private void GenerateGetMethods()
    {
        var barType = typeof(Foo).GetNestedType("Bar", BindingFlags.NonPublic);
        if (barType == null)
        {
            Debug.LogError("未找到Foo内部的Bar类");
            return;
        }

        var fields = barType.GetFields(BindingFlags.Public | BindingFlags.Instance);
        var methodBuilder = new StringBuilder();

        foreach (var field in fields)
        {
            // 生成GetX()格式的方法
            var methodName = $"Get{char.ToUpper(field.Name[0])}{field.Name.Substring(1)}";
            methodBuilder.AppendLine($"    public static {field.FieldType.Name} {methodName}()");
            methodBuilder.AppendLine("    {");
            methodBuilder.AppendLine($"        return _bar.{field.Name};");
            methodBuilder.AppendLine("    }");
            methodBuilder.AppendLine();
        }

        // 写入Foo.cs文件(请根据实际路径调整)
        var scriptPath = Path.Combine(Application.dataPath, "Scripts/Foo.cs");
        var originalContent = File.ReadAllText(scriptPath);

        // 找到插入位置(假设原有代码有"// 需要其他类能够访问x、y、z"注释)
        var insertMarker = "// 需要其他类能够访问x、y、z";
        var insertIndex = originalContent.IndexOf(insertMarker) + insertMarker.Length;
        var newContent = originalContent.Insert(insertIndex, "\n" + methodBuilder.ToString());

        File.WriteAllText(scriptPath, newContent);
        AssetDatabase.Refresh();
        Debug.Log("Get方法生成完成");
    }
}

使用方式:在Unity编辑器中点击Tools/生成Foo字段Get方法,弹出窗口后点击"一键生成",脚本会自动在Foo类中添加所有字段的Get方法。

优缺点:编译时校验安全,性能无损耗;新增字段只需运行生成器,无需手动编写代码,适合需要高性能的核心逻辑场景。


内容的提问来源于stack exchange,提问作者NGON

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 07:06:31