在 .NET 标准版中的属性中表示颜色



我正在使用.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; }
}

给我一个编译错误

属性参数

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

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

System.Drawing.KnownColor枚举本来是完美的,它存在于.NET Framework和.NET Core中,但不是.NET Standard,因为Xamarin没有它。(请参阅此 Github 线程(

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

谢谢

不应使用 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);

当你发现自己在.NET Standard中,System.Drawing.Common Nuget包,你有一个完美的匹配:

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

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

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

此列表甚至可以通过简单的 T4 转换自动生成(参见示例(,列表可以通过以下方式获得:

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

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

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

使用类型本身的属性解决

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)

最新更新