如何在公共静态类中自动获取私有内部类的公共属性?
解决方案
根据你的场景限制(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
相关产品推荐
相关产品推荐

