Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How decorate in structuremap?

I try it decorate IProjectService but I can't find documentation for struturemap

For<IProjectService>().Use<ProjectServiceLogDecorator>();
For<IProjectService>().Use<ProjectService>()
                      .DecorateWith((context, decorator) =>   
                                  context.GetInstance<ProjectServiceLogDecorator>());

What I do wrong?

exeption:

Bi-directional dependency relationship detected! Check the StructureMap stacktrace below: 1.) new ProjectServiceLogDecorator(Default of IRepository, Default of IUnitOfWork, Default of IProjectService, Default of IPrincipal, Default of AuditEventLogger) 2.) Project.Services.Projects.ProjectServiceLogDecorator 3.) Instance of Project.Services.Projects.ProjectServiceLogDecorator 4.) FuncInterceptor of Project.Services.Projects.IProjectService: IContext.GetInstance() 5.) Project.Services.Projects.ProjectService 6.) Instance of Project.Services.Projects.IProjectService (Project.Services.Projects.ProjectService) 7.) new UsersController(Default of IUserService, Default of IService, Default of IUserNotificationService, Default of IService, Default of IProjectService, Default of ILicenseGroupService) 8.) Project.Web.Api.Controllers.UsersController 9.) Instance of Project.Web.Api.Controllers.UsersController 10.) Container.GetInstance(Project.Web.Api.Controllers.UsersController)

I found solution but it is disgustingly:

For<IProjectService>().Use<ProjectService>().DecorateWith((ctx, service) => 
    new ProjectServiceLogDecorator(
        ctx.GetInstance<IRepository<Project>>(),
        ctx.GetInstance<IUnitOfWork>(),
        service,
        ctx.GetInstance<ILicenseService>(),
        ctx.GetInstance<IPrincipal>(),
        ctx.GetInstance<AuditEventLogger>()
    )
);
like image 730
Mediator Avatar asked Jul 30 '15 08:07

Mediator


1 Answers

Although there is no documentation yet, there are a complete set of unit tests showing all of the different ways you can configure a decorator pattern. I believe the one you want is:

For<IProjectService>().DecorateAllWith<ProjectServiceLogDecorator>();
For<IProjectService>().Use<ProjectService>();

You can add additional decorators simply by doing the following. However, note that the outermost decorator is the last .DecorateAllWith specified, so it might be more intuitive to specify the innermost class first.

For<IProjectService>().Use<ProjectService>();
For<IProjectService>().DecorateAllWith<ProjectServiceLogDecorator>();
For<IProjectService>().DecorateAllWith<SomeOtherDecorator>();

Which results in:

SomeOtherDecorator
    ProjectServiceLogDecorator
        ProjectService

If you need more control than that, you can always use smart instances to apply the constructor parameters to the decorator explicitly (without needing to supply all parameters explicitly).

var projectService = For<IProjectService>().Use<ProjectService>();
For<IProjectService>().Use<ProjectServiceLogDecorator>()
    .Ctor<IProjectService>().Is(projectService);
like image 171
NightOwl888 Avatar answered Oct 06 '22 01:10

NightOwl888