1

派生設定クラスに基づいて、正しい派生クラスを自動的にインスタンス化しようとしています。

ここには、基本設定クラスとともにメインの基本クラスがあります

public abstract class BaseClass
{
    public BaseClass() { }

    public abstract BaseClassSettings Write();
}

public class BaseClassSettings
{

}

ここに私の派生クラスとその設定クラスがあります

public class DerivedFoo : BaseClass
{
    public DerivedFoo(DerivedFooSettings settings) 
    { 
         // Apply settings
    }

    public override BaseClassSettings Write()
    {
        DerivedFooSettings settings = new DerivedFooSettings();

        return settings;
    }
}

public class DerivedFooSettings : BaseClassSettings
{

}

public class DerivedBar : BaseClass
{
    public DerivedBar(DerivedBarSettings settings) 
    { 
         // Apply settings
    }

    public override BaseClassSettings Write()
    {
        DerivedBarSettings settings = new DerivedBarSettings();

        return settings;
    }
}

public class DerivedBarSettings : BaseClassSettings
{

}

すべての派生クラスの設定を 1 つの配列に保存できます

DerivedFoo foo = new DerivedFoo();
DerivedBar bar = new DerivedBar();

BaseClassSettings[] s = new BaseClassSettings[2];
s[0] = foo.Write();
s[1] = bar.Write();

XML 形式でディスクにシリアル化されます。

派生設定クラスに基づいて派生クラスを自動的にインスタンス化するにはどうすればよいですか?

したがって、配列要素が DerivedBarSettings クラスの場合、DerivedBar クラスの新しいインスタンスを作成します。

クラスの数に応じて増え続けるelse ifステートメントを使用せずにこれを行いたいと思います。

if (BaseClassSettings is DerivedFooSettings)
    new DerivedFoo(settings)
else if (BaseClassSettings is DerivedBarSettings) 
    new DerivedBar(settings)

これはどのように行うことができますか?

================================================== =============================

[編集]

これが私が使用しているものです:

[
    XmlInclude(typeof(DerivedSettingsClassA)),
    XmlInclude(typeof(DerivedSettingsClassB)),
    XmlInclude(typeof(DerivedSettingsClassC)),
    XmlInclude(typeof(DerivedSettingsClassD)),
    XmlInclude(typeof(DerivedSettingsClassE)),
]
public abstract class BaseSettingsClass
{
    public abstract DerivedClass Load(Game1 game, OutputDimensionSettings settings);
}

これの唯一の欠点は、すべての派生クラスに対して XmlInclude を明示的に定義する必要があることです。

4

2 に答える 2

1

これは宿題ですか?

これが1つの方法です(他の可能性があります):

public abstract class BaseClass
{ 
  public abstract BaseClassSettings Write(); 
} 

public abstract class BaseClassSettings
{
  public abstract BaseClass CreateCorrespondingInstance();
} 

それで:

public class DerivedFoo : BaseClass             
{             
  public DerivedFoo(DerivedFooSettings settings)              
  {              
    // Apply settings             
  }             

  public override BaseClassSettings Write()             
  {             
    DerivedFooSettings settings = new DerivedFooSettings();             
    return settings;             
  }             
}             

public class DerivedFooSettings : BaseClassSettings             
{             
  public override BaseClass CreateCorrespondingInstance()
  {
    return new DerivedFoo(this);
  }
}         

しかし、ジェネリックの恩恵を受けることができるようです!

于 2012-05-29T16:00:01.593 に答える
0

ここでジェネリックが大いに役立つかどうかはわかりません。ジェネリックは、コンパイル時まで不明な型を延期または制約するために使用されます。あなたがしているのは、無関係なタイプ間の関係を作成することです。これは、カスタム属性とリフレクションを使用して実行できます。

まず、カスタム属性:

    [System.AttributeUsage(System.AttributeTargets.Class)]
    public class BaseClassLinkAttribute : System.Attribute
    {
        public System.Type LinkedType { get; set; }

        public BaseClassLinkAttribute(Type linkedType)
        {
            // Probably wat to make sure type is derrived from BaseClass
            LinkedType = linkedType;
        }
    }

ここで、カスタム属性で型のインスタンスを作成する静的メソッドを基本クラスに追加します。

public abstract class BaseClass 
{ 
    public BaseClass() 
    { 
    } 

    public abstract BaseClassSettings Write();

    public static BaseClass CreateFromSettings(BaseClassSettings settings)
    {
        Attribute attr = Attribute.GetCustomAttribute(settings.GetType(), typeof(BaseClassLinkAttribute));

        // Check for null here and throw exception if attribute can't be found in prduction code

        BaseClassLinkAttribute linkAttribute = (BaseClassLinkAttribute)attr;

        // This is only going to work if class implements a constructor
        // that take a base settings class

        return (BaseClass)Activator.CreateInstance(linkAttribute.LinkedType,settings);
    }
}

あとは、作成するクラスの属性で設定クラスをマークするだけです。

[BaseClassLink(typeof(DerivedFoo))]
public class DerivedFooSettings : BaseClassSettings
{
}

したがって、設定クラスを指定すると、関連するクラスを作成できます。

       DerivedFooSettings x = new DerivedFooSettings();

       BaseClass y = BaseClass.CreateFromSettings(x);

       Console.WriteLine(y.GetType().FullName);

Namespace.DerivedFoo の出力が得られます。

もちろん、ここにはいくつかの制限があります。派生クラスは、設定クラスを取るコンストラクターを実装する必要があります。そうしないと、アクティベーションが失敗します。属性を取り除き、ジェネリックで型を渡すことができるかもしれないと思います。ただし、タイプ間のリンクを作成する必要があります。

于 2012-05-29T19:01:01.907 に答える