依赖注入概念问题:在哪里实例化新对象以保存到数据库?

Dependency Injection conceptual problem: where to instantiate new object to save to the db?

我正在开发一个小玩具程序,以学习有关 .Net Core 3.1 上的 DI 和 IoC 的一些基础知识。

我有几个问题,主要是关于何时何地执行某些操作。

我为我的项目创建了以下架构:

DAL 层,Database First,具有数据库实体、上下文和实体的扩展,以及存储库的通用实现:

public class Repository<T> : IRepository<T> where T : BaseEntity
{
    private readonly DbContext context;
    private DbSet<T> entities;
    string errorMessage = string.Empty;

    public Repository(DbContext context)
    {
        this.context = context;
        entities = context.Set<T>();
    }

    public IEnumerable<T> GetAll()
    {
        return entities.AsEnumerable();
    }
    public T Get(Guid id)
    {
        //return entities.SingleOrDefault(s => s. == id);
        return null;
    }
    public void Insert(T entity)
    {
        try
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            entities.Add(entity);
            context.SaveChanges();
        }
        catch (Exception e)
        {
            //log ERROR
        }
    }
    public void Update(T entity)
    {
        try
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            context.SaveChanges();
        }
        catch (Exception e)
        {

            //log error
        }
    }
    public void Delete(T entity)
    {
        try
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            entities.Remove(entity);
            context.SaveChanges();
        }
        catch (Exception e)
        {

            //log error
        }
    }

    public void SoftDelete(T entity) {
        try
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            //context.SoftDelete(entity as EntityEntry);
            //context.SaveChanges();
        }
        catch (Exception e)
        {

            //log error
        }
    }
}

我还有一个服务和一个 WebAPI 层,具有单体架构(所有服务都在同一个包中,所有 API 请求都针对某个服务 class在所述包裹内)。

除了 Commons 层中的一些实用程序、异常和通用函数外,所有真正的业务逻辑都在服务层中。

另外,我有一个“领域”层,其中有 API 模型。例如,这些模型是我在收到 POST 请求时使用的模型。

我现在最大的问题是:where/when 以及如何创建数据库实体的新实例(来自 API 模型)?

现在我的服务层中有这个:

public class AnonymousLoginService : IAnonymousLoginService
{
    public IRepository<AnonymousLogin> _repository { get; set; }

    public AnonymousLoginService(IRepository<AnonymousLogin> repository)
    {
        _repository = repository;
    }


    public void SaveNewLogin(AnonymousLoginModel newEntry)
    {
        //HOW TO DO THIS CORRECTLY?
        var itemToSave = new AnonymousLogin();
        itemToSave.Username = newEntry.Username;
        itemToSave.Id = Guid.NewGuid();
        itemToSave.IsDeleted = false;
        itemToSave.LoginDate = DateTimeOffset.Now.ToString();
        itemToSave.Ipaddress = newEntry.Ipaddress;

        ValidationResult validation = (ValidationResult)itemToSave.ValidateSelf<IAnonymousLogin>();

        if (validation.IsValid)
        {
            _repository.Insert(itemToSave);
        }
        else
            throw new Exception("OMG");
    }


}

AnonymousLoginModel 是来自 WEB Api 的对象(从 POST 请求的主体创建的对象)和 AnonymousLogin 是要成为的实体保存到数据库。 如您所见,我正在创建 AnonymousLogin 对象的新实例,但这直接违背了 DI。我应该在哪里创建新条目?这个实现是否正确?服务层是否应该知道 Web Api 模型和数据库对象?

另外,我对整个Domain Layer的概念很担心。它在一个单独的 package/project 中可以吗?所有这些模型都应该在 Web Api 本身内部吗? None 以上?

非常感谢您的帮助,因为很难得到直接的答案(大多数在线信息都是示例,并不真正适用于这种特定情况)。提前致谢!

依赖注入是将依赖对象传递到对象本身的概念。在这种情况下,将 IRepository<AnonymousLogin> repository 传递给 AnonymousLoginService 意味着 AnonmyousLoginService 依赖于 IRepository<AnonymousLogin>。它与传递给方法的参数无关。

如果您觉得最好在方法中进行关注点分离并实例化新的数据库模型以验证其是否有效,而不是将用户输入作为数据库模型接受并传入。没关系。

在单独的应用程序中拥有领域层一点也没有错。特别是如果您不想为每个构建的应用程序都创建一个新的域层。可以通过这种方式使用领域层来松散地耦合代码,并为多个应用程序提供一个单一的领域层。假设方法 return 类型、方法名称和方法参数不变,对域层的更改不应破坏依赖于它的任何项目。

就让 api 了解两种类型的模型(db 和 api 模型)而言,听起来比让领域层了解两种类型的模型要好得多。领域层可能会更好地服务于只了解领域模型,然后每个使用领域层的应用程序也可以访问领域模型。与其让领域层理解来自多个项目的模型,唯一要考虑的是领域模型应该有多安全?也许有一组虚拟域模型(public 面向数据库模型)和一组私有数据库模型(实际数据库模型)和域层提供对虚拟模型的访问,然后从那里实例化实际的数据库模型。确保封装了实际的逻辑和代码。