Injecting dependencies into Entity Framework entit

2019-07-15 02:45发布

问题:

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?

回答1:

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.



回答2:

@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) { ... }