C# - 通过构造函数自动初始化 class 的字段(手动与动态)

C# - Auto-initialization of class's fields via the constructor (manual vs dynamic)

我偶然发现了一个案例,它不影响我的设计,但很可能会影响未来代码和性能的变化。

我的class如下:

public sealed class Commands {
public interface ICommand {
    string commandName { get; set; }
}

public ICommand Maintain;
public ICommand Dispatch;
public ICommand Memorize;
//............//

private class ReckonCommand : ICommand {
    public string commandName { get; set; }

    public ReckonCommand (string name) {
        this.commandName = name;
    }
}

public Commands () {
    Maintain = new ReckonCommand ("Maintain") as ICommand;
    Dispatch = new ReckonCommand ("Dispatch") as ICommand;
    Memorize = new ReckonCommand ("Memorize") as ICommand;
}

此方法需要手动初始化命令 class 中的每个 ICommand 变量。因此,当字段变多时,将变得难以维护。

另一种动态方法如下:

public ICommand Maintain;
public ICommand Dispatch;
public ICommand Memorize;
//............//

private class ReckonCommand : ICommand {
    public float commandName { get; set; }
    //Stuff

}

public Commands () {
    System.Reflection.FieldInfo[] _fields = GetType ().GetFields ();
    for (int i = 0; i < _fields.Length; i++) {
        if (_fields [i].FieldType == typeof(ICommand)) {
            _fields [i].SetValue (this, new ReckonCommand () as ICommand);
        }
    }
}

然而,命令 class 预计会被初始化多次(忽略名称,如果这会妨碍您理解),因此性能损失可能会在某些时候产生影响。

我正在使用的这个特定设计是否有替代方案?我关心的是在 Commands 的构造函数中自动初始化每个 ICommand 字段 class.The 手动方法容易出错,当发现时可能为时已晚。

动态方法是完全可以接受的(我们一直在大规模应用程序中使用它来解决您所描述的问题)。

但是,您应该在 class 的静态构造函数中实现发现并将结果存储在静态集合中,这样您就不必在每次 [= 的实例时都执行反射17=] 已创建。

大致如下:

    private static System.Collections.Generic.List<System.Reflection.FieldInfo> _fields;

    static Commands()
    {
        _fields = new System.Collections.Generic.List<System.Reflection.FieldInfo>();

        var fields = typeof(Commands).GetFields();
        var commandType = typeof(ICommand);

        foreach (var field in fields)
        {
            if (field.FieldType == commandType)
            {
                _fields.Add(field);
            }
        }
    }

    public Commands()
    {
        foreach (var field in _fields)
        {
            field.SetValue(this, new ReckonCommand() as ICommand);
        }
    }