1

我正在使用 Mvc3 和Unity.Mvc3来构建一个可测试和解耦的站点,但我显然做错了什么。

在我的Application_Start()我注册了一个依赖:

// container is a property of the MvcApplication
// and the HierarchicalLifetimeManager should make sure that the registrations
// only last for this request (or should it?)
_container.Register<Interface, Class>(new HierarchicalLifetimeManager())   

然后在Session_Start()我尝试解决我的依赖关系以将一些数据保存到会话中:

var obj = _container.Resolve<Interface>();

此时我得到一个异常说Unity无法解析接口,但我以为我为那个接口注册了一个类???

我很茫然,找到解决方案越来越难。

编辑:

这是我的整个代码,省略了一些不必要的部分:

public class MvcApplication : System.Web.HttpApplication  
{   
    // as EDIT 2 says, this is wrong...
    //private IUnityContainer _container = new UnityContainer();
   
    protected void Application_Start()
    {
        // mvc stuff, routes, areas and whatnot

        // create container here and it works, almost
        var container = new UnityContainer();

        // register dependencies            
        string connectionString = "String from config";
        container.RegisterInstance<DbContext>(new CustomContext(connectionString), new HierarchicalLifetimeManager())
                 .RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager())
                 .RegisterType(typeof(IRepository<>), typeof(Repository<>), new HierarchicalLifetimeManager());

        // register controller resolver
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));

        // if i try to resolve repos here, it works and they all have the same context
        // just like the unit of work
    }

    protected void Session_Start()
    {
        // here the container complains that it can't resolve the interface
         
        // wrong
        //var userRepo = _container.Resolve<IRepository<User>>();

        // right, but still failes, because it is resolving DbContext
        // instead of using the CustomContext instance
        var userRepo = DependencyResolver.Current.GetService<IRepository<User>>();

        // save some user data to session           
    }
}


public class SampleController : Controller {

    // here the container tries to resolve the System.Data.Entity.DbContext
    // instead of just giving the repo that instance that I registered
    public SampleController(IRepository<Entity> repo) {
    }

}

我显然在这个工作单元,依赖注入的东西上失败了,最糟糕的是我不知道为什么......所以在我开始拔牙之前请帮忙。

编辑2:

部分在那里。如果我按上述方式创建容器,它会在Session_Start(). 如果我在 中创建它Application_Start()作为局部变量,并使用DependencyResolver,它可以工作。怎么打,为什么打我?

但它仍在尝试解决DbContext而不是CustomContext实例。

解决方案:

好的,这是交易:

问题1)访问容器Session_Start()

如 EDIT 2 中所述,使用本地容器变量可以解决该问题,并通过DependencyResolver作品访问容器。

问题2)解析注册的数据库上下文实例:

事实证明,注册实例不起作用。但这确实:

container.RegisterType<DbContext, CustomContext>(null, new HierarchicalLifetimeManager(), new InjectionConstructor(connectionString))

但我并不真正感到满意,因为我仍然不明白为什么会这样。看来我很长一段时间都需要读一本书什么的。

提前谢谢了。

4

2 回答 2

1

与其直接访问容器(从你的 Q 中不清楚你在哪里获得对容器的引用?),为什么不让 MVC 依赖解析器解决它呢?

设置依赖解析器(Application_Start()):

DependencyResolver.SetResolver(new UnityDependencyResolver(container));

解决您的界面(Session_Start()):

var obj = DependencyResolver.Current.GetService<IMyInterface>();
于 2013-02-13T20:07:16.783 回答
1

问题是您使用RegisterInstance的是HierarchecalLifetimeManager. 我猜你正在尝试为每个请求获取一个新实例,因为 Unity.Mvc3 项目使用 LifetimeManager 来发挥这种魔力(以及 HttpModules 来管理子容器的创建和销毁)。

问题是,当一个新请求进来时,它会想要构造一个新对象,但不知道怎么做;您只是在应用程序启动时注册了一次实例,而不是创建对象的方法。所以你需要使用 RegisterType() 才能工作。

你有两个选择:

  1. 使用 InjectionConstructor 指定注入值:RegisterType<DbContext, CustomContext>(new HierarchecalLifetimeManager(), new InjectionConstructor(connectionString))

  2. 使用工厂:(Container.RegisterType<DbContext>(new InjectionFactory(c => new CustomContext(connectionString)), new HierarcicalLifetimeManager())受此启发

*注意:参数顺序可能有误。

如果您想要为整个应用程序提供一个真正的单例实例,请使用ContainerControlledLifetimeManager()(这实际上是 RegisterInstance 的默认值,因此您甚至不需要指定它)。但是随着站点的使用,您的 DbContext 将变得相当大。

此外,关于未在 Session_Start() 中注册的项目的初始问题:

ASP.NET 维护一个 HttpApplication 类池。这意味着如果您将 Unity 容器设为成员变量,您将拥有多个实例,它们都有自己的注册。Application_Start() 只被调用一次,而 Session_Start() 可以使用没有注册的不同实例调用。您需要使用静态变量来解决这个问题(这就是您最终使用 DependencyResolver 所做的事情)。

于 2013-02-14T05:42:11.457 回答