1

Как вы выполняете инъекцию свойств с помощью простого инжектора.Инъекция простого инжектора

с Ninject вы делаете это в соответствии с ревом:

[Inject] 
public IUnitOfWork UnitOfWork { get; set; } 

Как я могу сделать эквивалент это с простой форсункой. Я попытался найти решение в Интернете, но не повезло.

Почему я хочу использовать Инъекции свойств?

Я хочу использовать инъекции свойства для установки единицы работы в моем регуляторе так, что она будет создавать новую единицу работы OnActionExecuting и зафиксировать изменения OnResultExecuted. Это также означает, что мне не нужно проходить в UoW с каждым новым контроллером, который я создаю через конструктор.

+3

это [в документах] (http://simpleinjector.readthedocs.org/en/latest/extensibility.html#overriding-property-injection-behavior) – qujck

+0

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

+0

Вопрос обновлен. Cheers –

ответ

3

Другой вариант заключается в использовании RegisterInitializer метод:

container.RegisterInitializer<BaseControllerType>(controller => 
{ 
    controller.UnitOfWork = container.GetInstance<IUnitOfWork>(); 
} 

Он сохраняет все конфигурации в корневой состав и не загрязняет окружающую среду ваша база кода со всеми атрибутами.

Update: (как обещали)

Хотя это прямой ответ на ваш вопрос, я должен предоставить вам лучший вариант, так как использование базового класса для этого является IMO не правильный дизайн по нескольким причинам.

  1. Абстрактные классы могут стать реальными классами пита, поскольку они имеют тенденцию расти к классу бога, который имеет все виды перекрестных проблем режущими
  2. Абстрактный класс, особенно при использовании инъекций собственности, скрывает необходимые зависимости.

С акцентом на пункте 2. Если вы хотите модульное тестирование контроллера, который наследуется от базового контроллера, вы не имеете никакого способа знать, что этот контроллер зависит от IUnitOfWork. Это можно решить с помощью инъекции конструкторы вместо инъекции собственности:

protected abstract class BaseController : Controller 
{ 
    protected readonly IUnitOfWork uoW; 
    protected BaseController (IUnitOfWork uoW) 
    { 
     this.uoW = uoW; 
    } 

} 
public class SomeController : BaseController 
{ 
    public SomeController(IUnitOfWork uoW) : base(uoW) { } 
} 

В то время как это решает пункт 2, пункт 1 по-прежнему скрывается. Основная причина, по которой вы хотите, как вы говорите, состоит в том, что вы не хотите фиксировать свои изменения в каждом методе Action. Изменения должны быть сохранены контекстом, когда запрос будет выполнен.И думать о дизайне таким образом - это хорошо, потому что сохранение изменений есть или может рассматриваться как cross cutting concern, а способ реализации этого более или менее известен как AOP.

Если дело доходит до AOP, особенно если вы работаете с атомарными действиями в методах действий ваших контроллеров, есть намного лучше, больше SOLID и более гибкий дизайн, который имеет дело с этим очень красиво.

Я имею в виду шаблон Command/Handler, который подробно описан here (также читается this for the query part of your application).

С помощью этих шаблонов вы не вводите общую абстракцию, а вводите необходимые абстракции ICommandHandler<TCommand>.

Методы действий уволили бы ответственного манипулятора за это конкретное действие. Все CommandHandlers могут просто быть оформлены одним открытым родового SaveChangesCommandHandlerDecorator, «ValidationDecorator», «CheckPermissionsDecorator», и т.д. ...

Быстрый пример:

public class MoveCustomerCommand 
{ 
    public int CustomerId; 
    public Address NewAddress; 
} 

public class MoveCustomerCommandHandler : ICommandHandler<MoveCustomerCommand> 
{ 
    public void Handle(MoveCustomerCommand command) 
    { 
     // retrieve customer from database 
     // change address 
    } 
} 

public class SaveChangesCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand> 
{ 
    private readonly ICommandHandler<TCommand> decoratee; 
    private readonly DbContext db; 

    public SaveChangesCommandHandlerDecorator(
      ICommandHandler<TCommand> decoratee, DbContext db) 
    { 
     this.decoratee = decoratee; 
     this.db = db; 
    } 

    public void Handle(TCommand command) 
    { 
     this.decoratee.Handle(command); 
     this.db.SaveChanges(); 
    } 
} 

// Register as 
container.Register(typeof(ICommandHandler<>), new []{Assembly.GetExecutingAssembly() }); 
container.RegisterDecorator(typeof(ICommandHandler<>), 
         typeof(SaveChangesCommandHandlerDecorator<>)); 

// And use in controller as 
public ActionResult MoveCustomer(int customerId, Address address) 
{ 
    var command = new MoveCustomerCommand 
        { CustomerId = customerId, Address = address }; 
    this.commandHandler.Handle(command); 

    return View(new ResultModel()); 
} 

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

+0

Это похоже на лучшее решение thanx. Я дам этому ходу –

+0

@ShaneVanWyk см. Мой обновленный ответ, как и было обещано [здесь] (http://stackoverflow.com/questions/34984021/sessionperwebrequest-uow-simpleinjector-actionfilterattribute#comment57776338_34984021) –

+0

Спасибо за обновление, похоже отличное решение. Я отдам это. –

2

нужно создать следующее:

Сначала нужно создать класс атрибута

[System.AttributeUsage(System.AttributeTargets.Property] 
public class Inject : Attribute 
{ 
} 

Затем создать поведение пользовательских свойств

class PropertySelectionBehavior<TAttribute> : IPropertySelectionBehavior 
where TAttribute : Attribute 
{ 
    public bool SelectProperty(Type type, PropertyInfo prop) 
    { 
     return prop.GetCustomAttributes(typeof(TAttribute)).Any(); 
    } 
} 

Наконец, сообщающий контейнер использовать нестандартное поведение

container.Options.PropertySelectionBehavior = new PropertySelectionBehavior<Inject>(); 

Все, что осталось сделать, это украсить свойство с атрибутом

[Inject] 
public IUnitOfWork UnitOfWork { get; set; } 
Смежные вопросы