在 .NET Standard 的属性中表示颜色

Representing a color in an Attribute in .NET Standard

我正在使用 .NET Standard 2.0,我想创建一个颜色为 属性 的自定义属性。

例如:

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

问题是这个属性应该是常量或者原始类型,在编译时解决。

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

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

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

给我一个编译错误

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.

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

System.Drawing.KnownColor enum would have been perfect, it exists in .NET Framework and .NET Core but not .NET Standard because Xamarin doesn't have it. (See this Github thread)

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

谢谢

您可以通过将 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;
}

您不应使用 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),值可以按原样使用(例如渲染为HTML时)或转换为另一种结构(如果,例如,客户端是 WPF 或其他支持 .NET Standard 的绘图框架。在前一种情况下,它可以(假设您在 WPF 应用程序中以 .NET Framework 为目标)简单如下:

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

作为 yourself in .NET Standard the 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].

标记您的自定义属性

在类型本身中使用 属性 解决了问题

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)