C# 抽象方法来强制更新方法

Tom*_*Tom 3 c# generics abstract-class domain-driven-design

在我们的代码库中,我们有一个基本模型 ( PersistenceEntity),它处理通过通用存储库持久存储到存储中的任何模型。这适用于获取、添加和删除。我想要改进的地方是我们的 update 方法被封装在存储库中,而不是在服务层中获取对象,对其进行操作(以开发人员认为合适的任何方式)然后保存它。

存储库更新方法应该在内部加载模型,调用对象上的更新方法然后保存它(或调用 AddOrUpdate 扩展)。

为此,我想我可以在基类上添加一个抽象方法,以强制开发人员在模型中实现更新,而不是在另一层中设置属性。

public abstract T Update<T>(T existing) where T : PersistenceEntity;
Run Code Online (Sandbox Code Playgroud)

因此,这将使开发人员编写一个像这样的模型:

public class MyClass : PersistenceEntity 
{
        public override MyClass Update<MyClass>(MyClass existing)
        {
            existing.SomeProperty = SomeProperty;
            existing.SomeProperty2 = SomeProperty2;
            return existing;
        }
}
Run Code Online (Sandbox Code Playgroud)

但是当我以这种方式实现它时,编译器会抱怨它认为MyClass是 T 的名称而不是具体的类。我想我在这里遗漏了一些明显的东西,但我看不到它......任何建议将不胜感激。

Pav*_*ski 5

您可以通过使PersistenceEntity类本身成为泛型来避免通过类型参数隐藏类

public abstract class PersistenceEntity<T> where T : PersistenceEntity<T>
{
    public abstract T Update(T existing);
}
Run Code Online (Sandbox Code Playgroud)

这意味着自引用泛型约束,因为每个继承的类PersistenceEntity都应该更新自身类型的现有实例。

的实现MyClass如下:

public class MyClass : PersistenceEntity<MyClass>
{
    public override MyClass Update(MyClass existing)
    {
        existing.SomeProperty = SomeProperty;
        existing.SomeProperty2 = SomeProperty2;
        return existing;
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是创建一个不变的接口,它封装了Update方法(如果不允许使PersistenceEntity类通用)

public interface IUpdate<T> where T : PersistenceEntity
{
    T Update(T existing);
}
Run Code Online (Sandbox Code Playgroud)

然后实现它

public class MyClass : PersistenceEntity, IUpdate<MyClass>
{
    public MyClass Update(MyClass existing)
    {
        existing.SomeProperty = SomeProperty;
        existing.SomeProperty2 = SomeProperty2;
        return existing;
    }
}
Run Code Online (Sandbox Code Playgroud)