1

外部のxmlファイルからコントロールの設定/プロパティをロードするスキン可能なコントロールライブラリがあります。これらXmlはスキンエディターアプリケーションで使用されるため、クラスは別のプロジェクトにあります。現在、質問です。コントロールはコンストラクターで xml オブジェクトを受け入れてビルドしControlますが、各コントロールを作成する適切な方法を見つける必要があります。

XML クラスの例:

[Serializable]
[XmlInclude(typeof(XmlButton))]
[XmlInclude(typeof(XmlGroup))]
[XmlType(TypeName="Control")]
public class XmlControl
{
    [DefaultValue(0)]
    public int Width { get; set; }

    [DefaultValue(0)]
    public int Height { get; set; }
 ...

およびコントロール タイプごとの派生タイプ

[Serializable]
[XmlType(TypeName = "Button")]
public class XmlButton : XmlControl
{
    public string Label { get; set; }
}

制御クラス

public class GUIControl : GUI3DBase
{
    public GUIControl(XmlControl skinXml)
    {
        SkinXml = skinXml;
...

public class GUIButton : GUIControl, IActionControl
{
    public GUIButton(XmlControl skinXml) : base(skinXml)
    {
    }
...

ここで助けが必要です。現時点では、渡された xml オブジェクトに基づいてコントロールを作成するメソッドがあります。

    public static GUIControl CreateControl<T>(T skinXml) where T : XmlControl
    {
        if (skinXml is XmlButton)
        {
            return new GUIButton(skinXml);
        }
        else if  (skinXml is XmlGroup)
        {
            return new GUIGroup(skinXml);
        }
        ....

私は約 30 のコントロールを持っており、"if はしご" が急速に成長しています。xml オブジェクト タイプをチェックしてから対応するコントロール タイプを作成する必要なく、これらのコントロールを作成する簡単な方法が欠けているように感じます。

TypeXml オブジェクトにプロパティを追加すると、循環依存が発生するため、追加できません。

優れたファクトリ メソッドまたは新しい構造レイアウトに関するヘルプは素晴らしいでしょう

4

3 に答える 3

2

わかりました、あなたのすべてのアイデアと少しの反省でこれを行う方法を見つけました。それが最善の方法かどうかはわかりませんが、うまく機能し、新しいスキン可能なコントロールを追加するには、新しい xml オブジェクトとコントロール クラスの属性のみが必要です。

属性クラス

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class XmlControlTypeAttribute : Attribute
{
    protected Type xmlType;

    public XmlControlTypeAttribute(Type xmlType)
    {
        this.xmlType = xmlType;
    }

    public Type XmlType
    {
        get { return this.xmlType; }
    }
}

コントロール:

[XmlControlType(typeof(XmlButton))]
public class GUIButton : GUIControl, IActionControl
{
    public GUIButton(XmlControl skinXml) : base(skinXml)
    {
    }
    ....
}

工場方式:

public static GUIControl CreateControl2<T>(T skinXml) where T : XmlControl
{
    var controlType = Assembly.GetExecutingAssembly().DefinedTypes
        .Where(t => t.BaseType == typeof(GUIControl) && t.GetCustomAttribute<XmlControlTypeAttribute>().XmlType.Equals(typeof(T)))
        .FirstOrDefault();

    return (GUIControl)Activator.CreateInstance(controlType, new[] { skinXml }, null);
}

ヒープを助けてくれたすべてのアイデアに感謝します。誰かがこれよりも良い解決策を持っている場合に備えて、この質問をもう少し開いたままにします。

于 2013-01-09T12:08:03.733 に答える
2

多分IDictionary<Type, Func<XmlControl, GUIControl>>助けになるでしょう。このようなもの:

private static Dictionary<Type, Func<XmlControl, GUIControl>> _dictionary = new Dictionary<Type, Func<XmlControl, GUIControl>>()
                                                                                    {
                                                                                        {typeof (XmlControlImpl), x => new GUIControl(x)},
                                                                                        {typeof (XmlGroup), x => new GUIGroup(x)},
                                                                                    }; 

public static GUIControl CreateControl<T>(T skinXml) where T : XmlControl
{
    Func<XmlControl, GUIControl> builder;
    if (!_dictionary.TryGetValue(typeof(T), out builder))
        throw new KeyNotFoundException("");

    return builder(skinXml);
}                            
于 2013-01-09T10:46:47.140 に答える