将依赖项注入实体框架实体和项目

时间:2016-07-16 02:21:32

标签: c# entity-framework linq dependency-injection simple-injector

有没有办法将依赖项注入从EF Linq context.Entities.Select(x => new Y {...})投影返回的对象中? (我使用的是Simple Injector,但概念仍然存在)

我想要实现的一些事情:(这只是输入,没有编译,抱歉任何语法错误/不完整)

// 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 Framework中是否有任何钩子允许我将对象(通过DI)传递给创建的模型?

3 个答案:

答案 0 :(得分:5)

ObjectContext.ObjectMaterialized个事件。你可以勾住它。但一般而言,将域名服务注入域名实体并不是一个好主意。你可以找到很多关于这个主题的文章。

答案 1 :(得分:4)

@Oryol是对的,在构建is a bad idea期间将应用程序组件注入到域对象中,就像它是the other way around一样。

一种解决方案是使用方法注入而不是构造函数注入。这意味着每个域方法都将它所需的服务定义为方法参数。例如:

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

答案 2 :(得分:0)

理想情况下,您不希望实体本身出现这种情况,因为您通常会保持清洁。您可以使用存储库模式来做到这一点,它是您的 Person 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);
  }
  ...
}

您也可以考虑只在 person DTO 或 viewmodel 中拥有该属性,因为这听起来像是您想要在 UI 中显示但未存储在您的数据库中,因此不是您的实体模型的一部分。这为您提供了更多填充它的选项(例如工厂)。