代码之家  ›  专栏  ›  技术社区  ›  David Shnayder

如何只允许使用Action<Class>方法修改类属性?

  •  2
  • David Shnayder  · 技术社区  · 2 年前

    我有一个类处理一些用户界面的东西,让我们调用这个类和实例用户界面为例。

    在这个类中,我将有一个颜色类型的对象:

    public class Colors {
        public ConsoleColor Primary { get; set; } = ConsoleColor.White;
        public ConsoleColor Default { get; set;  } = ConsoleColor.Gray;
        public ConsoleColor Input { get; set; } = ConsoleColor.Gray;
        public ConsoleColor Success { get; set; } = ConsoleColor.Green;
        public ConsoleColor Error { get; set; } = ConsoleColor.Red;
        public ConsoleColor Highlight { get; set; } = ConsoleColor.Blue;
    }
    

    public static class UI {
        public static readonly Colors Colors = new();
    
        public static void ConfigureColors(Action<Colors> modification) {
            modification.Invoke(Colors);
        }
    }
    

    问题是,我希望能够像这样访问UI外部的Colors属性的getter:

    var primaryColor = UI.Colors.Primary;
    

    但不是二传手。。。 现在,这两项都起作用了:

    UI.ConfigureColors(colors => {
        colors.Primary = ConsoleColor.Yellow;
    });
    
    UI.Colors.Primary = ConsoleColor.Green;
    

    但是我只希望能够使用ConfigureColors()方法设置颜色。 我本来以为会是这样的,因为我将Colors属性设置为readonly,但它并不像我想要的那样工作。

    我试着在Colors类中处理属性的可访问性,比如使它们成为只读或“私有集”,但我想到的所有修改都导致这两个选项都不起作用。

    3 回复  |  直到 2 年前
        1
  •  1
  •   Olivier Jacot-Descombes    2 年前

    您可以通过声明getter-only属性的接口公开颜色。然后,实现也可以具有setter:

    public interface IColors
    {
        ConsoleColor Primary { get; }
        ConsoleColor Default { get; }
        ConsoleColor Input { get; }
        ConsoleColor Success { get; }
        ConsoleColor Error { get; }
        ConsoleColor Highlight { get; }
    }
    
    public class Colors : IColors
    {
        public ConsoleColor Primary { get; set; } = ConsoleColor.White;
        public ConsoleColor Default { get; set; } = ConsoleColor.Gray;
        public ConsoleColor Input { get; set; } = ConsoleColor.Gray;
        public ConsoleColor Success { get; set; } = ConsoleColor.Green;
        public ConsoleColor Error { get; set; } = ConsoleColor.Red;
        public ConsoleColor Highlight { get; set; } = ConsoleColor.Blue;
    }
    

    如下配置:

    public static class UI
    {
        public static readonly IColors Colors = new Colors();
    
        public static void ConfigureColors(Action<Colors> modification)
        {
            modification.Invoke((Colors)Colors);
        }
    }
    

    用法示例:

    var primary = UI.Colors.Primary;       // Okay
    
    UI.Colors.Primary = ConsoleColor.Gray; // Error CS0200  Property or indexer 
                                           // 'ConfigurableColors.IColors.Primary'
                                           // cannot be assigned to --it is read only
    
        2
  •  1
  •   Markus    2 年前

    您可以创建一个只发布getter的接口:

    public interface  IColors {
        ConsoleColor Primary { get; }
        ConsoleColor Default { get; }
        ConsoleColor Input { get; }
        ConsoleColor Success { get; }
        ConsoleColor Error { get; }
        ConsoleColor Highlight { get; }
    }
    

    班级 Colors 应实现此接口:

    public class Colors: IColors
    {
      // ...
    }
    

    而不是将类用于 UI 类,则使用该接口:

    public static class UI {
        private static readonly Colors _colors = new();
    
        public static IColors Colors { get => _colors; }
    
        public static void ConfigureColors(Action<Colors> modification) {
            modification.Invoke(Colors);
        }
    }
    

    这会阻止在使用 UI.Colors.Primary 符号,并允许使用操作进行写入-至少只要调用方不将接口强制转换到类:

    ((Colors)UI.Colors).Primary = ConsoleColor.Green;
    
        3
  •  0
  •   Klaus Gütter    2 年前

    您可以将Colors类拆分为只读接口和修改接口,如下所示:

    public interface IColors {
        ConsoleColor Primary { get; }
        ConsoleColor Default { get; }
        ConsoleColor Input { get; }
        ConsoleColor Success { get; }
        ConsoleColor Error { get; }
        ConsoleColor Highlight { get; }
    }
    
    public interface IModifyableColors {
        ConsoleColor Primary { get; set; }
        ConsoleColor Default { get; set; }
        ConsoleColor Input { get; set; }
        ConsoleColor Success { get; set; }
        ConsoleColor Error { get; set; }
        ConsoleColor Highlight { get; set; }
    }
    

    这两个接口都将由类实现 Colors (可以设置为私人课程):

    class Colors : IColors, IModifyableColors
    {
        public ConsoleColor Primary { get; set; } = ConsoleColor.White;
        public ConsoleColor Default { get; set;  } = ConsoleColor.Gray;
        public ConsoleColor Input { get; set; } = ConsoleColor.Gray;
        public ConsoleColor Success { get; set; } = ConsoleColor.Green;
        public ConsoleColor Error { get; set; } = ConsoleColor.Red;
        public ConsoleColor Highlight { get; set; } = ConsoleColor.Blue;
    }
    

    然后,UI类将仅公开只读接口:

    public static class UI {
        static readonly Colors _colors = new();
    
        public static IColors Colors => _colors;
    
        public static void ConfigureColors(Action<IModifyableColors> modification) {
            modification.Invoke(_colors);
        }
    }