设计这个类层次结构的最佳方法是什么

本文关键字:最佳 方法 是什么 层次结构 | 更新日期: 2023-09-27 18:07:41

我有一个数据库表,其中包含一个ID列和一个Name列。我的任务是设计一个程序,接受其中一个ID作为Main()的参数。

粗体为编辑2

我需要使用数据库中必须存在的ID,以对应于要运行的某些代码。表中的每一行对应的代码略有不同,但其中许多行共享大量代码。我需要一个能最大限度地减少代码重复的设计。

到目前为止,我开发的是一个抽象基类,它有一个抽象的Int32字段ID来强制派生类在数据库中具有相应的ID。这样,我就可以对派生类进行反思,找到ID与Main()参数匹配的类,并实例化该类。然后,我只调用Main()中的虚拟方法,它运行已定义的派生代码最多。

public abstract class Base {
    public abstract Int32 Id { get; }    
    public void Foo() {
        // Do something
    }
}
public class Derived {
    public override Int32 Id { get { return 42; } } 
    public void Foo() {
        // Do something more specific
    }
}

有人有更好的想法来实现我想要的吗?我喜欢在类定义中保留ID的正确性,但如果有意义的话,我愿意更改它。

谢谢!

编辑:

我不喜欢的一点是,我必须反思每个派生类型,并实例化该类型以检查ID。有人对如何做到这一点有更好的想法吗?

设计这个类层次结构的最佳方法是什么

不要使用属性来定义类的ID,而是使用自定义属性。这样,您就不必实例化对象来检查其ID是什么

当程序运行时,它可以扫描程序集中具有该属性标记的所有类,找到具有匹配ID的类,实例化该类,然后运行它的Foo方法。如果您在每次应用程序运行中多次执行这种查找,则可以使用自定义属性初始化所有类,然后将它们放入字典中,以提供按ID的快速查找。

你的代码可能看起来像这样:

[AttributeUsage(AttributeTargets.Class)]
public class CommandAttribute {
    public CommandAttribute(int id) {
        ID = id;
    }
    public int ID { get; private set; }
}
public abstract class Command {
    public abstract void Execute();
}
[Command(2)]
public class MyCommand : Command {
    public override void Execute() {
        //Do something useful
    }
}

使用自定义属性的另一个优点是,您必须显式标记所有候选对象,以便通过ID进行实例化和执行,而不是假设从基类派生的任何对象都是候选对象。如果您在类之间共享代码,您可能希望为它们创建一个公共基类,该基类派生自基类,但不应单独实例化或执行。

有一件事我不明白,如果要运行的类是由ID标识的,那么"名称"字段有什么意义?如果您可以决定每个ID的名称,那么您可以使用name字段作为要执行的类的完全限定类型名称,这样就可以避免扫描程序集中的所有类型(或应用程序域,具体取决于搜索范围(。然而,这种设置更容易出现拼写错误。

听起来您需要实现一个工厂模式。

我会定义一个接口:

public interface IWidget
{
    void Foo();
}

然后是基类:

public abstract class WidgetBase : IWidget
{
    public void Foo()
    {
        this.Bar()
    }
    protected virtual void Bar()
    {
        // Base implementation
    }
}

工厂:

public static WidgetFactory
{
    public static IWidget Create(int id)
    {
        // Get class name from id, probably use the name in your database.
        // Get Type from class name
        // Get constructor for Type
        // Create instance using constructor and return it.
    }
}

派生类:

public class DerivedWidget : WidgetBase
{
    protected override void Bar()
    {
        // call base implementation
        base.Bar();
        // derived implementation
    }
}

在你的主要:

public void Main(int id)
{
    var widget = WidgetBase.Create(id);
    widget.Foo();
}

我喜欢@Xinto使用工厂来完成这类任务的想法,但我认为我仍然会给出另一个答案。

实现原始设计的更好方法是将ID传递给基本构造函数,如下所示:

public abstract class Base {
    public Int32 Id { get; private set; }
    protected Base(Int32 id) {
            this.Id = id;
    }
    public void Foo() {
        // Do something
    }
}
public class Derived : Base {
    public Derived : base(42) {}
    public void Foo() {
        // Do something more specific
    }
}