Resolve() 是否为每个会话返回对象?

发布于 2024-10-11 04:37:13 字数 521 浏览 5 评论 0原文

在 Microsoft Unity IoC 中,如果我调用 Resolve(),我能否保证返回的对象是在当前会话期间创建的对象?

例如,三个用户登录,假设在容器中创建的 SomeType 对象对于每个用户都有不同的值。对 Resolve 的调用会返回为当前用户创建的对象吗?或者它会做一些愚蠢的事情,比如返回最后创建的一个?

由于一些环境问题,我自己测试时遇到了麻烦,我需要尽快检查一些东西,所以如果有人能回答这个问题,那将非常有帮助!

编辑

请原谅我对 Unity 非常陌生,但基于 我在这里读到的内容,似乎我应该能够使用唯一的名称在容器中注册对象并通过该名称检索它们。那么,我是否能够使用会话 ID 或会话中保留的其他值来检索我的对象?

In Microsoft Unity IoC, if I call Resolve<SomeType>(), can I guarantee that the object returned is the one that was created during the current session?

For example, three users sign on, and let's say that the object of SomeType that gets created in the container has different values for each user. Will a call to Resolve return the object that was created for the current user? Or would it do something stupid like return the last one that was created?

I'm having troubles testing this myself due to some environment problems and I need to check something in soon, so if someone could answer this it would be very helpful!

Edit

Forgive me for I am very new to Unity, but based on what I read here, it seems like I should be able to register objects in the container with a unique name and retrieve them by that name. So, wouldn't I be able to use a session ID or some other value that persists within a session to retrieve my object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不知在何时 2024-10-18 04:37:13

哇哦,在 am MVC 应用程序中使用 Unity 进行生命周期管理。我从哪里开始?

首先,会话单例实际上是不可能的,因为没有 ASP.NET 系统可以保证同一会话中的请求之间使用相同的实例。会话可以通过在请求之间序列化和反序列化来模仿会话中保留的同一对象。

瞬态实例 - 即没有生命周期管理规范的简单注册在 99% 的情况下就足够了。这意味着每次需要时都会创建注册类型的实例。

您很少需要实例在请求的整个生命周期中都存在。然而,当您需要这些时,您确实需要它们。与数据库的连接是一个完美的选择。另一方面,请求单例更容易创建和管理。

最优雅的解决方案是使用Unity的子容器功能。可以在请求开始时创建子容器,并在请求结束时处置(作为额外的好处,它将处置所有 ContainerControlledLifetimeManager 实例)。

创建子容器时,所有注册仍然可以从父容器获得,因此您需要向子容器注册请求特定的内容。

下面是实现此功能的伪代码:

private void Application_Start() {
  _parentContainer = new UnityContainer();
   //creates a transient registration, available at any point in the app.
  _parentContainer.RegisterType<IParentIntf, ParentIntfImpl>();
  ControllerBuilder.Current.SetControllerFactory(new ServiceLocatorControllerFactory());
}

private void Application_BeginRequest() {
  var childContainer = _parentContainer.CreateChildContainer();
  //registers a request "singleton"
  //This registration is a type registration, an instance of RequestInterfaceImpl
  //will be created when needed and then kept in the container for later use.
  childContainer.RegisterType<IRequestInterface,RequestInterfaceImpl>(new ContainerControlledLifetimeManager());
  //save the child container in the context, so we can use it later
  HttpContext.Items["childContainer"] = childContainer;
}

private void Application_EndRequest() {
  //dispose the child container
  ((IUnityContainer)HttpContext.Items["childContainer"]).Dispose();
}

需要做的另一件事是重写控制器工厂以使用子容器来创建控制器。控制器是应用程序的第一个入口点,它们可以简单地依赖于其构造函数中的其他组件。

public class UnityControllerFactory : DefaultControllerFactory {

    #region IControllerFactory Members

    public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) {
        IController controller;
        controllerName = controllerName.ToLower();
        var container = ((IUnityContainer)HttpContext.Items["childContainer"])
        if(container.IsRegistered<IController>(controllerName))
            controller = container.Resolve<IController>(controllerName);
        else 
            controller = base.CreateController(requestContext, controllerName) ;
        return controller;
    }
} 

Oh wow, lifetime management using Unity in am MVC app. Where do I start?

First of all, session singletons are not really possible as there is no ASP.NET system that will guarantee that the same instance will be used between requests in the same session. The session can mimic the same object persisted within the session by serializing and deserializing it between requests.

Transient instances - i.e. simple registrations without lifetime management specification are sufficient 99% of the time. This implies that an instance of registered type will be created every time it is needed.

It is very rarely that you need instances to live throughout the lifetime of the request. However when you need those, you really need those. A connection to a DB is a perfect candidate for this. Request singletons, on the other hand are much easier to create and manage.

The most elegant solution is to use Unity's child container feature. A child container can be created at the beginning of the request, disposed at the end of the request (as an added bonus it will dispose all ContainerControlledLifetimeManager instances).

When creating a child container, all registrations are still available from the parent container, so you need to register request specific stuff with the child container.

Here is pseudo-code to get this working:

private void Application_Start() {
  _parentContainer = new UnityContainer();
   //creates a transient registration, available at any point in the app.
  _parentContainer.RegisterType<IParentIntf, ParentIntfImpl>();
  ControllerBuilder.Current.SetControllerFactory(new ServiceLocatorControllerFactory());
}

private void Application_BeginRequest() {
  var childContainer = _parentContainer.CreateChildContainer();
  //registers a request "singleton"
  //This registration is a type registration, an instance of RequestInterfaceImpl
  //will be created when needed and then kept in the container for later use.
  childContainer.RegisterType<IRequestInterface,RequestInterfaceImpl>(new ContainerControlledLifetimeManager());
  //save the child container in the context, so we can use it later
  HttpContext.Items["childContainer"] = childContainer;
}

private void Application_EndRequest() {
  //dispose the child container
  ((IUnityContainer)HttpContext.Items["childContainer"]).Dispose();
}

One other thing that needs to be done is to override the Controller Factory to use the child container to create controllers. Controller are the first point of entry into the application and they could simply take a dependency on other components in their constructor.

public class UnityControllerFactory : DefaultControllerFactory {

    #region IControllerFactory Members

    public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) {
        IController controller;
        controllerName = controllerName.ToLower();
        var container = ((IUnityContainer)HttpContext.Items["childContainer"])
        if(container.IsRegistered<IController>(controllerName))
            controller = container.Resolve<IController>(controllerName);
        else 
            controller = base.CreateController(requestContext, controllerName) ;
        return controller;
    }
} 
一个人的旅程 2024-10-18 04:37:13

默认行为是为每个解析调用返回一个新实例,这不是您想要的。

可以在会话中创建和解析相同的实例,但据我所知,没有内置支持。您必须编写自己的生命周期管理器,然后在注册类型时使用它。

有一个生命周期管理器可以为每个线程实例执行操作,但这对于会话没有用,因为线程将被重用,并且解析还需要跨多个请求工作才能真正在会话范围内工作。

完全有可能有人为此编写了终身经理。

The default behaviour will be to return a new instance for each resolve call, this isn't what you want.

It would be possible to create and resolve the same instance within a session, but there is no built in support as far as I know. You would have to write your own lifetime manager, and then use this when registering your type.

There is a lifetime manager that can do per thread instances, but this isn't useful for sessions as threads will get re-used, and resolve would need to also work across multiple requests to be truly session-scoped.

It's entirely possible that someone has written a lifetime manager for this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文