在具有反射的类中使用常量

时间:2016-01-28 18:31:57

标签: c# string constants system.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);
       }
    }
}

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

非常感谢: - )

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

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

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();
}

答案 2 :(得分:0)

正如我在评论中提到的,你似乎试图实现一个&#34;状态机&#34;。这并不能直接回答您的问题,但它可以帮助您解决实际问题。状态被实现为真实State类的实际子类。这样,您就不需要任何ifcase语句来确定要运行哪个州的逻辑;每个子类都有一个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));
            }
        }
    }
}