Unity IoC和Static方法

时间:2011-02-01 23:36:52

标签: c# unity-container ioc-container ninject

处理您使用IoC的情况的最佳方法是什么,但其中有一个静态方法以及其他方法,如下所示:

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()
    {
        ...
    }
}

2 个答案:

答案 0 :(得分:2)

静态GetCart方法是Ambient Context。这是一个坏主意,特别是在域模型级别上有这样的方法。尝试将其重构为抽象工厂:

public interface IShoppingCartFactory
{
    ShoppingCart GetCartForCurrentUser();
}

您可以在需要它的服务中注入IShoppingCartFactory(但不在您的实体中,最好保持您的实体清洁)。现在,您可以定义一个实现并在IoC配置中注册它。以下是此类实现的示例:

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);
        }
    }
}

将获取用户上下文与购物卡工厂分开会更好。例如,您可以在购物卡工厂中注入IUserContextFactory,使其与ASP.NET无关。

答案 1 :(得分:0)

IMO你应该重构它,使它看起来像这样:

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()
    {
        ...
    }
}

通过这种方式,您将负责将当前购物车从静态方法转移到可以在表示层中注入的服务类。