将依赖项注入实体框架实体和项目[英] Injecting dependencies into Entity Framework entities and projects

本文是小编为大家收集整理的关于将依赖项注入实体框架实体和项目的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

是否有一种方法可以将依赖项注入从EF Linq context.Entities.Select(x => new Y {...})投影返回的对象中? (我正在使用简单的喷油器,但仍然存在概念)

我要实现的一种事情:(这只是输入而不是编译,对任何语法错误/不完整感到抱歉)

)

// person MAY be an entity, but probably more likely a class to serve a purpose
public class Person {
  public string Name
  public DateTime DOB {get;set; }

  // what I want to achieve: note, I don't want to have complex logic in my model, I want to pass this out to a Service to determine.. obviously this example is over simplified...
  // this could be a method or a property with a get accessor
  public bool CanLegallyVote()  
  {
    return _someServiceThatWasInjected.IsVotingAge(this.DOB);
  }

  private readonly ISomeService _someServiceThatWasInjected;
  public Person (ISomeService service)
  {
    _someServiceThatWasInjected = service;
  }
}

// then calling code... I can't pass ISomeService into the "new Person", as "Additional information: Only parameterless constructors and initializers are supported in LINQ to Entities."

// If the above model represents a non-entity...
var person = context.People.Select(person => new Person {Name = x.Name, DOB = x.DateOfBirth}).First;
// OR, if the above model represents an EF entity...
var person = context.People.First();

if (person.CanLegallyVote()) {...}

// I don't want to invoke the service from the calling code, because some of these properties might chain together inside the model, I.e. I do not want to do the following:
if (_service.CanLegallyVote(person.DOB))

Linq/Entity框架中是否有任何钩子可以使我将对象(通过DI)传递给创建的模型?

推荐答案

有ObjectContext.ObjectMaterialized事件.你可以挂上它.但是通常,将域服务注入域实体并不是一个好主意.您可以找到有关此主题的许多文章.

其他推荐答案

@oryol是正确的,在施工期间将应用程序组件注入域对象是一个坏主意,就像它是另一种围绕.

一种解决方案是使用注射方法代替构造函数注入.这意味着每个域方法都定义了所需的服务作为方法参数.例如:

public bool CanLegallyVote(ISomeService service) { ... }

其他推荐答案

理想情况下,您不希望在实体本身中使用它,因为这通常是您保持清洁的东西.您可以使用存储库模式来做到这一点,这是您的DBSET的抽象.该接口是通用的,并且实现为混凝土类型.

public interface IPersonRepository : IRepository<Person>
{
  ...
  public bool CanLegallyVote(Person person);
  public bool CanLegallyVote(int personId);
}

public class PersonRepository : IPersonRepository
{
  private readonly ISomeService _someService;
  public PersonRepository(ISomeService someService)
  {
    _someService = someService;
  }

  public bool CanLegallyVote(Person person)
  {
    return _someService.CanLegallyVote(person.DOB);
  }
  ...
}

您还可以考虑仅将属性放在DTO或ViewModel中,因为它听起来像是要在UI中显示的内容,但不存储在数据库中,因此不在您的实体模型中.这为您提供了更多填充它的选择(例如工厂).

本文地址:https://www.itbaoku.cn/post/1556753.html

问题描述

Is there a way to inject dependencies into objects returned from an EF Linq context.Entities.Select(x => new Y {...}) projection? (I am using Simple Injector, but concept remains)

Sort of thing I am trying to achieve: (this is just typed in, not compiled, sorry for any syntax errors/incompleteness)

// person MAY be an entity, but probably more likely a class to serve a purpose
public class Person {
  public string Name
  public DateTime DOB {get;set; }

  // what I want to achieve: note, I don't want to have complex logic in my model, I want to pass this out to a Service to determine.. obviously this example is over simplified...
  // this could be a method or a property with a get accessor
  public bool CanLegallyVote()  
  {
    return _someServiceThatWasInjected.IsVotingAge(this.DOB);
  }

  private readonly ISomeService _someServiceThatWasInjected;
  public Person (ISomeService service)
  {
    _someServiceThatWasInjected = service;
  }
}

// then calling code... I can't pass ISomeService into the "new Person", as "Additional information: Only parameterless constructors and initializers are supported in LINQ to Entities."

// If the above model represents a non-entity...
var person = context.People.Select(person => new Person {Name = x.Name, DOB = x.DateOfBirth}).First;
// OR, if the above model represents an EF entity...
var person = context.People.First();

if (person.CanLegallyVote()) {...}

// I don't want to invoke the service from the calling code, because some of these properties might chain together inside the model, I.e. I do not want to do the following:
if (_service.CanLegallyVote(person.DOB))

Are there any hooks in Linq / Entity Framework that would allow me to pass an object (via DI) to models created?

推荐答案

There is ObjectContext.ObjectMaterialized event. You can hook it. But in general injecting domain services into domain entities isn't good idea. You can find many articles on this subject.

其他推荐答案

@Oryol is right, injecting application components into domain objects during construction is a bad idea, just like it is the other way around.

One solution is to use method injecting instead of constructor injection. This means that each domain method defines the services it requires as method arguments. For instance:

public bool CanLegallyVote(ISomeService service) { ... }

其他推荐答案

Ideally you don't want that in the entity itself since that is something you generally keep clean. You could do this with the repository pattern, which is an abstraction of your Person DbSet. The interface is generic and implementation is left up to the concrete type.

public interface IPersonRepository : IRepository<Person>
{
  ...
  public bool CanLegallyVote(Person person);
  public bool CanLegallyVote(int personId);
}

public class PersonRepository : IPersonRepository
{
  private readonly ISomeService _someService;
  public PersonRepository(ISomeService someService)
  {
    _someService = someService;
  }

  public bool CanLegallyVote(Person person)
  {
    return _someService.CanLegallyVote(person.DOB);
  }
  ...
}

You could also consider only having the property in a person DTO or viewmodel because it sounds like something that you want to display in your UI but is not stored in your database and therefore not part of your entity model. This gives you many more options to populate it (e.g. factory).