使用反射获取 class 中使用的常量

Getting used constants in a class with reflection

所以...请看这个例子:

public class StatesList() {
    public const string State1Name = "State1";
    public const string State2Name = "State2";
    public const string State3Name = "State3";
}

public class Test() {

    private currentState = StatesList.State1Name;

    public static void Main(string[] args) {
        while(true) {
            if(currentState == StatesList.State1Name) {
                State1();
            } else if (currentState == StatesList.State3Name) {
                State2();
            }
        }
    }

    public void ChangeState(string newState) {
       currentState = newState;
    }

    public void State1() {
       // do stuff.
       if(iAmSilly) {
           ChangeState(StatesList.State3Name);
       }
    }

    public void State2() {
       // do stuff.
       if(!iAmSilly) {
           ChangeState(StatesList.State1Name);
       }
    }
}

我想要实现的是能够 "parse" 测试 class 并创建一个包含所用状态名称的列表。在示例中,我希望能够创建一个包含 StatesList.State1Name 和 StatesList.State3Name 的列表。是否可以使用反射来实现它,或者我实际上是否必须创建一个解析器(将 cs 文件作为文本加载)来实现它?

非常感谢:-)

反射是不可能的。无法通过反射获得源代码;只有元数据。常量在编译后被替换为它们的字面值,所以即使你查看 class 的 IL,你也无法判断是否使用了常量或字面量字符串。

解析源代码可能是您的最佳选择。

使用正则表达式并解析文件:

private static List<string> GetUsedConstants(string path_to_file, string const_class)
{
    var text = File.ReadAllText(path_to_file);

    var rx = new Regex(const_class + @"\.\w+");

    return rx.Matches(text).Cast<Match>().Select(m => m.Value).Distinct().ToList();
}

正如我在评论中提到的,您似乎通过尝试实现 "State Machine"。这并不能直接回答您的问题,但可以帮助您解决实际问题。状态被实现为真实状态 class 的实际子classes。这样你就不需要任何 ifcase 语句来找出哪个状态的逻辑 运行;每个 subclass 都有一个 Execute 方法,它有自己的状态特定逻辑。如果这听起来像你感兴趣的东西,请告诉我,我会为你做一个简单的例子。

控制台应用程序中状态机的一个非常简单的示例。它在 2 个状态之间切换,其中一个状态从 1 计数到 5,第二个状态从 1 计数到 10。

using System;

namespace StateMachineExample
{
    class Program
    {
        static void Main(string[] args)
        {
            SimpleStateMachine sm = new SimpleStateMachine();
            sm.ChangeState(new State1(sm));
            sm.Run();
        }
    }

    class SimpleStateMachine
    {
        private State _currentState;
        public void Run()
        {
            while (true)
            {
                _currentState.Execute();
            }
        }

        public void ChangeState(State newState)
        {
            Console.WriteLine($"Changing state to: {newState.GetType()}");
            _currentState = newState;
        }
    }

    abstract class State
    {
        public State(SimpleStateMachine sm)
        {
            StateMachine = sm;
        }

        protected SimpleStateMachine StateMachine { get; }

        public abstract void Execute();
    }

    class State1 : State
    {
        public State1(SimpleStateMachine sm) : base(sm) { }

        private int _num = 0;
        public override void Execute()
        {
            _num = _num + 1;
            Console.WriteLine(_num);

            if (_num > 10)
            {
                StateMachine.ChangeState(new State2(StateMachine));
            }
        }
    }

    class State2 : State
    {
        public State2(SimpleStateMachine sm) : base(sm) { }

        private int _num = 0;
        public override void Execute()
        {
            _num = _num + 1;
            Console.WriteLine(_num);

            if (_num > 5)
            {
                StateMachine.ChangeState(new State1(StateMachine));
            }
        }
    }
}