Using Unity.WebForms in ASP.NET

2020-02-26 13:08发布

问题:

I am trying to implement DI in a webforms project, so I installed the Unity.WebForms dlls in my UI layer. As soon as I did an App_Start folder was created for me with a UnityWebFormsStart class file. Inside this file there is a method RegisterDependencies which asks to be edited.

What is the next step after registering the dependencies? Is there something I need to add in the Global.asax class file? And how and where do I resolve a type inside a webform? Do I decorate that with any attributes?

回答1:

The Unity.WebForms dll and NuGet package does a few things for you in the background. It will ensure that a child container is started at the begin of each new web request and disposed at the end of each request. This allows you to register components with a 'per web request' lifestyle (using the HierarchicalLifetimeManager in Unity), which is useful for components such as O/RM unit of works such as Entity Framework's DbContext.

The other thing that the package ensures is that the given HttpHandler (usually your Page) and all its child controls are Built up. The BuildUp method is the way to initialize components that are not created by the container itself.

So the idea is to use property injection in your page classes and controls, but solely use constructor injection in ALL other components in your application. Constructor injection is the preferred mechanism for doing dependency injection, but constructor injection is unfortunately not possible in ASP.NET Page and Control classes.

So your page could look like this:

public class CancelOrderPage : Page
{
    [Dependency]
    public ICommandHandler<CancelOrder> CancelOrderHandler { get; set; }

    void CancelButton_Click(object sender, EventArgs e) {
        this.CancelOrderHandler.Handle(new CancelOrder {
            OrderId = Guid.Parse(this.OrderIdHiddenField.Value)
        });
    }
}

For the rest of your application, use constructor injection:

public class CancelOrderHandler : ICommandHandler<CancelOrder>
{
    private readonly IAuthorizedRepository<Order> orderRepository;
    private readonly IEventPublisher eventPublisher;

    public CancelOrderHandler(IAuthorizedRepository<Order> orderRepository,
        IEventPublisher eventPublisher) {
        this.orderRepository = orderRepository;
        this.eventPublisher = eventPublisher;
    }

    public void Handle(CancelOrder command) {
        // some implementation
    }
}

In the RegisterDependencies you will have to register your dependencies. You can do this manually:

container.RegisterType<ICommandHandler<CancelOrder>, CancelOrderHandler>();
container.RegisterType<IEventPublisher, InProcessPublisher>();
container.RegisterType(
    typeof(AuthorizedRepository<>), 
    typeof(DbContextRepo<>));

Or you can use batch-registration.