0

Предположим, у меня есть класс User, который частично заполнен ORM, но есть некоторые части данных, которые логически связаны с этой сущностью, которые предоставляются из других источников.Поведение Инъекция в сущность или лучший способ?

public class User { 
    public int Id { get; set; } 

    public int ServiceId { get; set; } 

    public string FirstName => null; //this comes from somewhere else 

    public ICollection<Role> Roles { get; set; } 
    //etc... 
} 

Ранее, в случаях, подобных этому, я был позволяя один интерфейс, который будет введен в модель домена контейнером МОК справиться с этим.

public class User { 
    public readonly IUserBehavior _userBehavior; 

    public User() {} 
    public User(IUserBehavior userBehavior) { 
    _userBehavior = userBehavior; 
    } 

    public int Id { get; set; } 

    public int ServiceId { get; set; } 

    public string FirstName => _behavior?.getFirstName(this); 

    public ICollection<Role> Roles { get; set; } 
    //etc... 
} 

я недавно, однако, пытался переход от NHibernate к Entity Framework, который выглядит сделать это невозможно (по крайней мере, в той мере, с помощью инъекции конструктора).

Мои параметры сейчас представляют собой перемещение служебного вызова (детали реализации) для получения отсутствующих данных непосредственно в сущности или использования двойного шаблона отправки, который кажется скорее выключенным ... Некоторые свойства данных этого типа будут иметь чтобы быть вызванным особым образом. Если бы это выполняло действие для изменения состояния, я мог видеть, что двойная диспетчеризация имеет больше смысла. В качестве альтернативы, я полагаю, я мог бы вернуться к nHibernate.

Я предполагаю, что я спрашиваю, есть ли какие-либо из моих опций на самом деле «хорошие», или есть какой-то другой вариант, который я должен рассмотреть?

+0

Дубликат https://stackoverflow.com/questions/28715966/entity-framework-object-materialization-and-dependency-injection? – Steven

+0

@Steven Пила этот вопрос, прежде чем я написал этот. Кажется, предполагает двойную отправку, что, как я сказал, кажется странным для моего случая использования. – Ixonal

+0

Я не вижу, как это связано с двойной отправкой, за исключением случаев, когда вы начинаете публикацию событий, что кажется не связанным с вашим вопросом. – Steven

ответ

0

Используйте декоратор, чтобы обеспечить необходимую функциональность: https://en.wikipedia.org/wiki/Decorator_pattern

Так что с вашего бизнес-слой (или там, где вам нужно получить доступ User класс, вы могли бы назвать класс декоратора, который будет первым назвать EF, а затем использовать свой собственный процесс для обеспечения FirstName и тому подобное.

+1

Собственно, это может сделать трюк ... – Ixonal

+0

Это не образец Decorator, так как декоратор - это класс, который реализует ту же абстракцию, что и обертывание. То, что вы описываете, - это Builder или Pipeline. – Steven

+0

@Steven Итак, я думал о расширении исходного класса данных с помощью Decorator, вызывая оригинальную функцию для извлечения данных из Decorator, а затем вызывающий частный метод в классе Decorator для получения дополнительных данных. Это звучит как узор декоратора для меня. Builder трубопровода потребовал бы, чтобы я назвал как Decorator, так и исходный класс доступа к данным от потребителя. Здесь я бы назвал Decorator только у потребителя – bc004346

0

Как объяснено несколькими людьми here, here и here, с помощью инъекции конструктора, чтобы ввести в зависимости субъектов не является хорошей идеей.

Вместо этого вы гораздо лучше используете метод инъекции. Пример:

public class User { 
    public int Id { get; set; } 
    public int ServiceId { get; set; } 
    public ICollection<Role> Roles { get; set; } 

    public string GetFirstName(IUserBehavior behavior) => behavior.GetFirstName(this); 

    //etc... 
} 

Здесь каждый метод сущности определяет свой собственный набор зависимостей, которые вводятся с использованием метода инжекции. Это делает методы для объектов очень надежными и предотвращает необходимость создания объекта с помощью контейнера.

Вместо этого служба-потребитель получит необходимые зависимости, введенные в его конструктор, и передаст эти зависимости методам, которые он вызывает.

В этом случае поведение метода GetFirstName() настолько прост, что вам, вероятно, лучше, позвонив по телефону behavior.GetFirstName(User).

Смежные вопросы