【问题标题】:Representing a color in an Attribute in .NET Standard在 .NET Standard 中的属性中表示颜色
【发布时间】:2018-08-14 08:47:45
【问题描述】:

我使用的是 .NET Standard 2.0,我想创建一个带有颜色属性的自定义属性。

例如:

public class DesignAttribute : Attribute
{
    public int Width { get; set; }
    public ??? BackgroundColor { get; set; }
}

问题是这个属性应该是一个常量或者原始类型并且在编译时被解析。

所以它的类型不能是 System.Drawing.Color 也不能是 int 用于 ARGB 表示,因为

public class FooModel
{
    [Required]
    public int Id { get; set; }

    [DesignAttribute(Width = 20, BackgroundColor = Color.Red.ToArgb())]
    public string Name { get; set; }
}

给我一​​个编译错误

属性参数必须是属性参数类型的常量表达式、typeof表达式或数组创建表达式。

我还尝试使用 Byte[] 并用我的静态颜色类的 A、R、G 和 B 属性填充它,但我得到了同样的错误。即使使用 string 并将其设置为 Color.Red.Name 也不起作用。

System.Drawing.KnownColor 枚举本来是完美的,它存在于 .NET Framework 和 .NET Core 但不存在于 .NET Standard,因为 Xamarin 没有它。 (见Github thread

所以我想知道我在 .NET Standard 中的选择是什么?如何将颜色表示为有效的属性参数?

谢谢

【问题讨论】:

    标签: c# colors custom-attributes .net-standard


    【解决方案1】:

    您不应该使用 GDI+ System.Drawing.Color 或 WPFSystem.Windows.Media.Color,因为您已经注意到它们不可移植。您可以定义自己的一组常量,但这是一项乏味的工作,就像重新发明轮子一样,幸运的是 WPF 本身(和 HTML ......)给了我们一个提示:

    public class DesignAttribute : Attribute
    {
        public int Width { get; set; }
        public string BackgroundColor { get; set; }
    }
    

    现在你可以拥有:

    public class FooModel
    {
        [Required]
        public int Id { get; set; }
    
        [DesignAttribute(Width = 20, BackgroundColor = "red"]
        public string Name { get; set; }
    }
    

    当然你要支持多种格式(比如#abcdef),value可以按原样使用(比如渲染成HTML时)或者转换成另一种结构(比如client是WPF或者其他支持 .NET Standard 的绘图框架。在前一种情况下,它可以(假设您在 WPF 应用程序中以 .NET Framework 为目标)很简单:

    var color = (Color)colorConverter.ConvertFromString(attribute.BackgrouncColor);
    

    作为you found 自己在 .NET Standard 中的System.Drawing.Common Nuget 包,你有一个完美的匹配:

    var color = ColorTranslator.FromHtml(attribute.BackgroundColor);
    

    如果你想避免使用魔法字符串,那么你可以创建一个简单的颜色列表:

    static class Colors {
        public const string Red = "red";
    }
    

    这个列表甚至可以使用简单的T4 transformation 自动生成(参见示例),列表可以通过以下方式获得:

    typeof(Colors).GetProperties(BindingFlags.Static | BindingFlags.Public)
        .Select(x => ((Color)x.GetValue(null)).ToString());
    

    注意:不要忘记用[Serializable] 标记您的自定义属性。

    【讨论】:

    • 非常感谢。我从KnownColor 中的所有值生成了一个ArgbConstants 类,但我想我会为您提供ColorConverter 类的解决方案(注意ConvertFromString 不是静态方法,因此ColorConverter 的实例必须被创建)
    • 实际上我的问题是关于 .NET Standard。ColorConverter 类存在于 .NET Framework 和 .NET Core 中,但不存在于 .NET Standard 中。取而代之的是System.Drawing.ColorTranslator.FromHtml(myStringColor)。我今天刚刚在我的 .NET Standard 库中尝试了您的解决方案,并意识到......
    • 是的,当您在 .NET Framework WPF 客户端中使用该库时,我建议使用 ColorConverter(否则即使您已经针对 .NET Framework,也没有必要向其程序集添加依赖项) .我不知道ColorTranslator,非常好!
    • 今天我发现自己很困惑,不记得我在哪里找到了这个ColorTranslator 类。它还不是 .NET Standard 的一部分,但包含在可以在 .NET Standard 库中引用的 Nuget 包中。我更新了你的答案
    【解决方案2】:

    您可以通过将BackgroundColor 设置为常量来解决编译器错误。

    public class FooModel
    {
        [Required]
        public int Id { get; set; }
    
        [DesignAttribute(Width = 20, BackgroundColor = Constants.RedArgb)]
        public string Name { get; set; }
    }
    
    public static class Constants
    {
        public const int RedArgb = -65536;
    }
    

    【讨论】:

      【解决方案3】:

      使用类型本身的属性解决

      public class MyClass
      {
          [MyAttribute(BackgroundColorPropertyName = nameof(MyPropertyColor))]
          public string MyProperty { get; set; }
      
          public static Color MyPropertyColor {get; set;} = Color.Red;
      }
      

      然后使用

      (Color)from.GetProperty(attribute.BackgroundColorPropertyName, 
          BindingFlags.Static | BindingFlags.Public)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-13
        • 1970-01-01
        • 2020-10-29
        • 1970-01-01
        相关资源
        最近更新 更多