Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否解决<;T>;()每个会话返回对象?_C#_Asp.net Mvc_Unity Container_Ioc Container - Fatal编程技术网

C# 是否解决<;T>;()每个会话返回对象?

C# 是否解决<;T>;()每个会话返回对象?,c#,asp.net-mvc,unity-container,ioc-container,C#,Asp.net Mvc,Unity Container,Ioc Container,在Microsoft Unity IoC中,如果调用Resolve(),是否可以保证返回的对象是在当前会话期间创建的对象 例如,三个用户登录,假设在容器中创建的SomeType对象对每个用户具有不同的值。调用Resolve是否会返回为当前用户创建的对象?或者它会做一些愚蠢的事情,比如返回最后一个创建的 由于一些环境问题,我自己测试这个有困难,我需要尽快检查一些东西,所以如果有人能回答这个问题,那将非常有帮助 编辑 请原谅,我对Unity非常陌生,但基于,似乎我应该能够使用唯一的名称在容器中注册对

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

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

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

编辑


请原谅,我对Unity非常陌生,但基于,似乎我应该能够使用唯一的名称在容器中注册对象,并使用该名称检索它们。那么,难道我不能使用会话ID或会话中持续存在的其他值来检索我的对象吗?

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

可以在会话中创建和解析同一个实例,但据我所知,没有内置的支持。您必须编写自己的lifetime manager,然后在注册类型时使用它

有一个生命周期管理器可以处理每个线程的实例,但这对会话没有用处,因为线程将被重用,而resolve还需要跨多个请求工作,才能真正确定会话范围


完全有可能有人为此编写了一个终身管理器。

噢,哇,在am MVC应用程序中使用Unity进行终身管理。我从哪里开始

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

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

在请求的整个生命周期中,很少需要实例。然而,当你需要这些时,你真的需要它们。连接到DB是实现这一点的最佳选择。另一方面,请求单例更易于创建和管理

最优雅的解决方案是使用Unity的子容器特性。子容器可以在请求开始时创建,在请求结束时处理(作为额外的奖励,它将处理所有
containerControlled LifetimeManager
实例)

创建子容器时,父容器中的所有注册仍然可用,因此您需要向子容器注册特定于请求的内容

以下是使其正常工作的伪代码:

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();
}
private void应用程序\u Start(){
_parentContainer=新的UnityContainer();
//创建临时注册,可在应用程序中的任何位置使用。
_parentContainer.RegisterType();
ControllerBuilder.Current.SetControllerFactory(新ServiceLocatorControllerFactory());
}
私有无效应用程序_BeginRequest(){
var childContainer=_parentContainer.CreateChildContainer();
//注册请求“singleton”
//此注册是类型注册,是RequestInterfaceImpl的实例
//将在需要时创建,然后保存在容器中供以后使用。
RegisterType(新的ContainerControlledLifetimeManager());
//将子容器保存在上下文中,以便稍后使用
HttpContext.Items[“childContainer”]=childContainer;
}
私有无效应用程序_EndRequest(){
//处置子容器
((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;
    }
} 
公共类UnityController工厂:DefaultControllerFactory{
#区域IControllerFactory成员
公共覆盖IController CreateController(System.Web.Routing.RequestContext RequestContext,string controllerName){
i控制器;
controllerName=controllerName.ToLower();
var container=((IUnityContainer)HttpContext.Items[“childContainer”])
if(容器已注册(控制器名称))
控制器=container.Resolve(controllerName);
其他的
controller=base.CreateController(requestContext,controllerName);
返回控制器;
}
} 

@Samo您是如何注册对象的,您使用的是什么生命周期管理器?如果您使用RegisterInstance,那么您当然会得到相同的实例。我之前的评论(发生了一些初始化)是错误的,所以我删除了它。我使用的是RegisterType,因为不同的产品使用相同的代码,并且将在容器中注册不同的类。是否有一种方法可以满足我的两种需求?终身管理者是一个ContainerControlledLifetimeManager@Samo没有现成的东西可以为您提供会话范围的实例(它必须与ASP.Net会话状态管理集成,后者可能位于内存或SQL Server等中,而Unity本身并不能做到这一点)
ContainerControlled LifetimeManager
实际上会为您提供一个单一实例,即由
Resolve
的所有调用方共享的单个实例。您是如何管理您的容器的?例如,它是静态的吗?@Samo想出一个终身管理器可能不会太痛苦