简体   繁体   中英

StructureMap and Injection dependency “on the fly”

I am following this excellent article in order to create my own attribute in the mvc.net framework v2 . The Author , Simone Chiaretta, uses Ninject to inject dependency within an ActionFilter using the attribute [Inject] over the dependencies he has in his class.

I would like to know if the same kind of technics might be used with structuremap.

I hope to have given enough details, if not please ask.. ;)

yours,

UPDATE 1:

Here is some code to enlighten a bit my problem

public class GreetingAttribute :
ActionFilterAttribute,
ISuperActionFilter,IGreetingAttribute
{
    **[Inject]**
    public IGestioneUtenti _service { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        _service.Elenca();
        base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ViewResult result = filterContext.Result as ViewResult;
        _service.Elenca();

        if (result != null)
        {
            result.ViewData["Title"] += " - " ;
        }
    }
}

I would have loved to be able to have this [Inject] attribute. So that my InvokeActionMethodWithFilters would have looked like this :

protected override ActionExecutedContext InvokeActionMethodWithFilters(
    ControllerContext controllerContext, IList<IActionFilter> filters,
    ActionDescriptor actionDescriptor, IDictionary<string, object> parameters) 
{
    foreach (IActionFilter actionFilter in filters)
    {
        ISuperActionFilter superActionFilter = 
            actionFilter as ISuperActionFilter;
        if (superActionFilter != null)
        {
            ObjectFactory.DoInjectionForMarkedAttribute(actionFilter);
        }

    }
    return base.InvokeActionMethodWithFilters(
        controllerContext, filters, actionDescriptor, parameters); 
}

Below my final implementation in an answer.

My final solution (well up to now, because week end is arriving so fast.. :):

public class GreetingAttribute : ActionFilterAttribute, ISuperActionFilter,IGreetingAttribute { [SetterProperty] public IMyService _service { get; set; }

  public override void OnActionExecuting(ActionExecutingContext 

filterContext) { _service.Elenca(); base.OnActionExecuting(filterContext); }

  public override void OnActionExecuted(ActionExecutedContext 

filterContext) { ViewResult result = filterContext.Result as ViewResult; _service.Elenca();

  if (result != null) { result.ViewData["Title"] += " - " ; } } } 

and the StructureMapControllerActionInvoker:

public class StructureMapControllerActionInvoker : ControllerActionInvoker {

  public StructureMapControllerActionInvoker() { } protected override ActionExecutedContext InvokeActionMethodWithFilters( ...) { foreach (IActionFilter actionFilter in filters) { **ObjectFactory.Container.BuildUp(actionFilter);** } return base.InvokeActionMethodWithFilters( controllerContext, filters, actionDescriptor, 

parameters); } }

thanks for all your help

Yes, use ObjectFactory.GetInstance<WhatYouWant>()

It is the StructureMap equivalent to Ninject's KernelContainer.Kernel.Get<WhatYouWant>() like in the article you posted.

You can't make extension methods to ObjectFactory because it is a static class. If you look at th article you will see that the NinjectControllerActionInvoker accepts an IKernel in the constructor.

Similarly, you can receive an IServiceProvider implementation that wraps ObjectFactory in your constructor. For example:

public class StructureMapServiceProvider: IServiceProvider
{
    public object GetService(Type serviceType)
    {
        return ObjectFactory.GetInstance(serviceType);
    }

    public T GetService<T>()
    {
        return ObjectFactory.GetInstance<T>();
    }
}

Then, from within your StructureMapActionInvoker.InvokeActionMethodWithFilters , you can write

 if(actionFilter is ISuperActionFilter){
        var propertiesToInject = 
            GetType()
            .GetProperties(BindingFlags.Public|BindingFlags.Instance)
            .Select(p => new{ 
                InjectAttribute = p.GetCustomAttributes(typeof(InjectAttribute),true).FirstOrDefault(),
                PropertyInfo = p}
                )
                .Where(x=> x.InjectAttribute != null);
        foreach(var syringe in propertiesToInject)
        {
            syringe.PropertyInfo.SetValue(actionFilter, _serviceProvider.GetService(syringe.PropertyInfo.PropertyType), null);
        }
 }

..You're welcome

The SetterProperty attribute is equivalent to Ninject's Inject.

Also, take a look at this blog post: http://codebetter.com/jeremymiller/2008/10/09/setter-injection-in-structuremap-2-5/ for more details on setter injection in Structuremap. Unfortunately Some of the examples use an older syntax , but all the ideas apply.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM