Mike
Mike

Reputation: 107

Unity IoC and Static method

What is the best way to handle a situation where you're using IoC but there is a static method in it along with the other methods like the following:

public partial class ShoppingCart
{
    private IDatabaseFactory _storeDB;

    public ShoppingCart(IDatabaseFactory storeDB)
    {
        _storeDB = storeDB;
    }

    private string ShoppingCartId { get; set; }

    public static ShoppingCart GetCart(HttpContextBase context)
    {
        var cart = new ShoppingCart(WHATGOESHERE?);
        cart.ShoppingCartId = cart.GetCartId(context);
        return cart;
    }

    public int OtherMethod()
    {
        ...
    }
}

Upvotes: 2

Views: 2263

Answers (2)

Steven
Steven

Reputation: 172646

The static GetCart method is an Ambient Context. It's a bad idea, especially to have such a method at the level of your domain model. Try refactoring it to an abstract factory:

public interface IShoppingCartFactory
{
    ShoppingCart GetCartForCurrentUser();
}

You can inject the IShoppingCartFactory in services that need it (but not in your entities, it's better to keep your entities clean). Now you can define an implementation and register it in your IoC configuration. Here's an example of such an implementation:

public class HttpShoppingCartFactory : IShoppingCartFactory
{
    private readonly IShoppingUnitOfWorkFactory uowFactory;

    public HttpShoppingCartFactory(
        IShoppingUnitOfWorkFactory uowFactory)
    {
        this.uowFactory = uowFactory;
    }

    public ShoppingCart GetCartForCurrentUser()
    {
        int userId = (int)HttpContext.Current.Session["userId"];

        using (var unitOfWork = this.uowFactory.CreateNew())
        {
            return unitOfWork.ShoppingCards
                .FirstOrDefault(c => c.User.Id == userId);
        }
    }
}

It would be even better to separate the getting the user context from the shopping card factory. For instance, you yould inject a IUserContextFactory in the shopping card factory, making it independant on ASP.NET.

Upvotes: 2

onof
onof

Reputation: 17367

IMO you should refactor it, making it to look like this:

public class ShoppingCartService {
    private readonly IDatabaseFactory _storeDB;

    public ShoppingCartService(IDatabaseFactory storeDB) {
        _storeDB = storeDB
    }

    public ShoppingCart GetCart(IdType cartId)
    {
        var cart = new ShoppingCart(_storeDB);
        cart.ShoppingCartId = cartId;
        return cart;
    }
}

public partial class ShoppingCart
{
    private IDatabaseFactory _storeDB;

    public ShoppingCart(IDatabaseFactory storeDB)
    {
        _storeDB = storeDB;
    }

    private string ShoppingCartId { get; set; }

    public int OtherMethod()
    {
        ...
    }
}

This way, you are moving responsibility to get the current shopping cart from a static method to a service class you can inject in the presentation layer.

Upvotes: 0

Related Questions