C#泛型类型参数是否可以来自子类?

6

我想标题并没有太多说明,这里是解释。

我有一个父类,我希望它能够包含一个事件Action,其中T是任何子类继承它的类型。

例如,像这样:

abstract class ActiveRecord
{
  protected event Action<T> NewItem;
}

class UserRecord : ActiveRecord
{
  public UserRecord()
  {
    NewItem += OnNewItem; // NewItem would in this case be Action<UserRecord>
  }

  private void OnNewItem(UserRecord obj)
  {
    // Flush cache of all users, since there's a new user in the DB.
  }
}

所以问题是,上述是否可行,我在父类中应该使用什么作为T?
请注意,我不希望将一个通用参数传递给我的父类,因为这看起来真的很愚蠢,会影响可读性。
class UserRecord : ActiveRecord<UserRecord>

我正在开发一种基于继承的ORM,以防你想知道它是用来干什么的。每当ORM将数据插入数据库时,都会触发NewItem事件。
编辑:试图更好地澄清,使用正确的类命名。
ActiveRecord类位于一个单独的程序集中,而UserRecord位于我正在工作的Web项目中。(注意:我是两个部分的开发人员,但这是两个不同的项目)
我希望能够在成功插入行、删除行等操作时引发事件。事件应将相关记录作为参数传递给事件处理程序,因此需要Action。
然而,由于我在基类(ActiveRecord)中声明了这些事件,所以我需要一种方法将子类型传递给事件处理程序,以便获得强类型对象。
当然,我可以使用Action,然后在我的实现中进行类型转换,但这真的不太好 :-(
希望这样能更清楚地解决问题,否则请问一下 :-)
编辑2:只是想让你知道反射、动态方法或类似的东西是一个选项,如果有帮助的话。但是我对这个特定的场景表示怀疑 :-(

4
这里有些不对劲,孩子是您的模型项目,而父母是容器吗?还是反过来?您能再解释一下吗? - Daniel Mošmondor
3个回答

7

我不太建议这样做,但你可以使用C#版本的奇妙递归模板模式

class Parent<T> where T : Parent<T>
{
    protected event Action<T> NewItem;
}


class Child : Parent<Child>
{
    public Child()
    {
        NewItem += OnNewItem;
    }

    private void OnNewItem(Child obj)
    {
        // Do something
    }
}

在实践中,这将非常难以合理使用;老实说,必须有更好的解决方案来改进整体设计。

我同意这可能难以合理使用,而且由于其他人可能会使用该库,这是我的首要任务。但还是谢谢您的建议。 - Steffen
这似乎是最好的方式。 - Steffen

1

试试这个:

abstract class Parent<T>
{
    public event Action<T> NewItem;
}

class Child : Parent<Child>
{
    public Child()
    {
        NewItem += OnNewItem;
    }

    private void OnNewItem(Child obj)
    {
        // Do something 
    }
} 

如果您无法将Parent设置为abstract,则可以在ParentChild之间添加一个抽象过渡类。
class Parent<T>
{    
    public event Action<T> NewItem;
}

abstract class Transition<T> : Parent<T> { }

class Child : Transition<Child>
{
    public Child()
    {
        NewItem += OnNewItem;
    }
    private void OnNewItem(Child obj)
    {
        // Do something 
    }
} 

虽然那样做可以起作用,但我真的希望有一种方法可以避免在子类中使用通用参数。 - Steffen

0

其实我觉得我刚刚找到了一个更好的方法:

abstract class ActiveRecord
{
  protected virtual void OnNewItem() {}
}

class UserRecord : ActiveRecord
{

  protected override void OnNewItem()
  {
    // Still got the UserRecord object, now it's just "this"
  }
}

我觉得这个更加简洁,所以我会使用它。


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