如何从字符串"System.Drawing.Color"获取System.Type?

4
我有一个存储了某个控件的xml属性。
<Prop Name="ForeColor" Type="System.Drawing.Color" Value="-16777216" />

我希望将其转换为其他格式

System.Type type = System.Type.GetType(propertyTypeString);
object propertyObj = 
  TypeDescriptor.GetConverter(type).ConvertFromString(propertyValueString);

System.Type.GetType("System.Drawing.Color")返回null。

问题是如何正确从字符串中获取颜色类型

(最好不要为颜色属性做特殊处理)

更新

有时这个xml文件会手动编辑。


更改不会影响颜色本身(以防您此时正在查看Value属性)。 - jonny
4个回答

4

当使用Type.GetType()时,除非类型在mscorlib或当前执行的程序集中,否则需要指定程序集以及类型名称。

如果您知道它在System.Drawing程序集中,可以使用Assembly.GetType()代替 - 或者查看可能的程序集列表:

Type type = candidateAssemblies.Select(assembly => assembly.GetType(typeName))
                               .Where(type => type != null)
                               .FirstOrDefault();

if (type != null)
{
    // Use it
}
else
{
    // Couldn't find the right type
}

据我所知,GetType方法会抛出很多异常...即使你提供参数(throwOnErrors=false),它们仍然会抛出(啊~~~),所以你需要保护Select的内部lambda表达式,这使得代码变得不那么易读和清晰。 - Massimiliano
Assembly.GetType只在非常糟糕的情况下才会抛出异常——如果找到类型名称但依赖项已损坏,或者类型名称本身无效或为null。特别地,它不会仅因程序集中不包含该类型而引发异常。我认为这可能是期望的行为。 - Jon Skeet

2

你是否已经加载了 System.Drawing 程序集?你是否已经引用了它?


是的,我有它的引用,当我到达这一行时,我可以看到它已经加载了。 - jonny

2

您是否正在使用XML自行存储这些属性?如果是,只需在创建节点时写入对象的AssemblyQualifiedName而不是仅写入FullName。这样可以提供装配上下文信息,以便使用Type.GetType()从字符串加载类型。


+1 好的决定。如果有这个选项,它比搜索多个程序集要好。 - Joe White
就可预见性而言,它更好,但在可读性方面则不尽如人意,特别是如果它是带有版本字符串等签名程序集。 - Jon Skeet
也许在 System.Drawing 的情况下这不是问题,但如果您将 QualifiedName 用于某些自定义程序集,则可能会在这些程序集升级到另一个版本时遇到问题。 - Massimiliano
@Jon:我不确定我是否同意可读性方面。可读性实际上只应该被视为用户是否能够在查看XML时知道类型是什么。 "垃圾"(版本字符串,PK等)都在最后。类型和程序集名称在前面以相当易读的格式呈现。对于这样的事情,我希望终端用户的可变性不会成为一个问题,因为用户希望不会手动编辑那种信息。 - Adam Robinson
1
@Yacoder:你也可以认为假设不同版本的程序集兼容(特别是如果它们不在你的控制范围内)可能会引起同样多的问题。我相当确定(但我可能错了),除非程序集是强名称,否则绑定器将使用另一个同名的程序集,即使版本不匹配,因此不强制签名仍然可以正常工作。 - Adam Robinson

0

也许这与您的问题不完全相关,但我曾经遇到过类似的问题。我需要使用XmlSerializer序列化/反序列化颜色。在搜索互联网并结合几位作者的智慧后,我想出了包装器类:

/// <summary>
/// Color that can be xml-serialized
/// </summary>
public class SerializableColor
{
    public int A { get; set; }
    public int R { get; set; }
    public int G { get; set; }
    public int B { get; set; }
    public int KnownColor { get; set; }

    /// <summary>
    /// Intended for xml serialization purposes only
    /// </summary>
    private SerializableColor() { }

    public SerializableColor(Color color)
    {
        this.A = color.A;
        this.R = color.R;
        this.G = color.G;
        this.B = color.B;
        this.KnownColor = (int)color.ToKnownColor();
    }

    public static SerializableColor FromColor(Color color)
    {
        return new SerializableColor(color);
    }

    public Color ToColor()
    {
        if (KnownColor != 0)
        {
            return Color.FromKnownColor((KnownColor)KnownColor);
        }
        else
        {
            return Color.FromArgb(A, R, G, B);
        }
    }
}

也许它可以应用于你的情况。 你看,Color类有时不是以ARGB值的组合形式存储自身,而是作为一个KnownColor枚举值...需要在序列化期间保留。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接