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
{

}

我可以将所有派生类设置保存在一个数组中

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

这是作业吗?

这是一种方法(还有其他可能性):

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 回答