pghtech
pghtech

Reputation: 3702

Problem with Setter injection with Structuremap

I am creating an instance of a type scoped to HTTPContextScoped. I am trying to figure out how to inject this specific instance into a property of the same type into an attribute that I don't have control over.

I want to inject the specific instance of UnitOfWork into a property of IUnitOfWork type in an attribute (see code below)

Here is my ObjectFactory.Initialize() method of the part that I am referring to:

ObjectFactory.Initialize(x =>
{
    //...   
    //additional content
    //...

    x.For<IUnitOfWork>()
        .HttpContextScoped()
        .Use(context => new UnitOfWork(
            context.GetInstance<ISessionFactory>()));

    x.SetAllProperties(context =>
    {
        context.Matching(p => 
            p.DeclaringType == typeof(UnitOfWorkAttribute));
        context.OfType<IUnitOfWork>();
    });

Attribute Class:

public class UnitOfWorkAttribute : ActionFilterAttribute {

    public IUnitOfWork UnitOfWork { get; set; }

    public UnitOfWorkAttribute() {
        Order = 0;
    }

    public void OnActionExecuting(ActionExecutingContext filterContext) {
        UnitOfWork.Begin();
    }

    public void OnActionExecuted(ActionExecutedContext filterContext) {
        UnitOfWork.End();
    }
}

I was trying to follow one of Jeremy Miller's examples of using criteria to do so, but I am not doing something right.

Any thoughts of what I am doing incorrectly?

NOTE It does create the UnitOfWork instance as I use it else where, but I am specifically not correctly (or at all) injecting this attribute's property with that instance (or any for that matter).

Upvotes: 1

Views: 617

Answers (1)

Steven
Steven

Reputation: 172835

Try solving this problem by creating a factory for IUnitOfWork objects. Since the lifetime of unit of work instances must be controlled explicly (since you are doing Begin and End, controlling them yourself is much more logical, and adheres the principle of least surprise.

Here is an example of what you can do:

public interface IUnitOfWorkFactory
{
    IUnitOfWork NewUnitOfWork();
}

public class MyController : Controller
{
    private readonly IUnitOfWorkFactory factory;

    public MyController(IUnitOfWorkFactory factory)
    {
        this.factory = factory;
    }

    public void Operation()
    {
        using (var work = new this.factory.NewUnitOfWork())
        {
            work.Begin();

            // do some interesting stuff here.            

            work.End();
        }
    }
}

Upvotes: 1

Related Questions