为模型创建泛型Save()方法

本文关键字:方法 Save 泛型 模型 创建 | 更新日期: 2023-09-27 17:59:46

我有一个相当简单的系统,出于这个问题的目的,基本上有三个部分:模型、存储库和应用程序代码。

核心是模型。让我们用一个简单的人为例子:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

在同一个项目中有一个通用的存储库接口。最简单的是:

public interface IRepository<T>
{
    T Save(T model);
}

该接口的实现在一个单独的项目中,并注入了StructureMap。为了简单起见:

public class PersonRepository : IRepository<Person>
{
    public Person Save(Person model)
    {
        throw new NotImplementedException("I got to the save method!");
        // In the repository methods I would interact with the database, or
        // potentially with some other service for data persistence.  For
        // now I'm just using LINQ to SQL to a single database, but in the
        // future there will be more databases, external services, etc. all
        // abstracted behind here.
    }
}

所以,在应用程序代码中,如果我想保存一个模型,我会这样做:

var rep = IoCFactory.Current.Container.GetInstance<IRepository<Person>>();
myPerson = rep.Save(myPerson);

很简单,但感觉它可以自动化很多。这种模式适用于整个应用程序代码,因此我希望在所有模型上创建一个通用Save(),这只是对上述应用程序代码的简写调用。这样一来,人们只需要打电话:

myPerson.Save();

但我似乎想不出一种方法来做这件事。也许它看起来很简单,我只是没有从正确的角度来看待它。起初,我尝试创建一个空的ISaveableModel<T>接口,并打算让每个"可保存"的模型实现它,然后对于单个通用Save()方法,我将在接口上进行扩展:

public static void Save<T>(this ISaveableModel<T> model)
{
    var rep = IoCFactory.Current.Container.GetInstance<IRepository<T>>();
    model = rep.Save(model);
}

但它告诉我rep.Save(model)有无效的参数。它似乎没有像我希望的那样连接类型推理。我在BaseModel<T>类中尝试了类似的方法,模型将从中继承:

public class BaseModel<T>
{
    public void Save()
    {
        this = IoCFactory.Current.Container.GetInstance<IRepository<T>>().Save(this);
    }
}

但是编译器的错误是一样的。有没有办法实现我想要实现的目标?我在设计上非常灵活,所以如果我在建筑层面上做了一些完全错误的事情,那么我有空间退一步,改变大局。

为模型创建泛型Save()方法

一个通用的扩展方法能解决这个问题吗?

public static T Save<T>(this T current)
{
    var rep = IoCFactory.Current.Container.GetInstance<IRepository<T>>();
    rep.Save(current);
}

然后可以将其约束到ISaveableModel<T>接口。上面的返回类型没有实现,但您可以将其放在布尔值或状态标志中,不管怎样。

在这两种方法中,Save()函数的参数不是T类型。在第一个中,它是ISaveableModel<T>,在第二个中,是BaseModel<T>。由于存储库是基于T的泛型,因此Save方法将期望T类型的变量。在调用Save修复之前,您可以向T添加一个简单的强制转换。

或者,您的IRepostory<T>可以更改为

public interface IRepository<T>
{
    T Save(ISaveableModel<T> model);
}

这更有意义。