StructureMap同一接口多构造参数实例按HttpContextLifecycle缓存问题
问题根源
- 使用
ExplicitArguments传参时,StructureMap会默认绕过生命周期缓存,每次强制生成新实例,因此第一次尝试无法复用同HttpContext下的实例。 - 遍历注册时仅用
Add()注册多实例,既未指定默认实例也未给实例加唯一标识,TryGetInstance默认只会匹配默认实例,因此返回空值。
解决方案一(命名实例方案,适配遍历注册思路)
第一步:修改Registry注册逻辑,给每个枚举对应的实例加唯一名称
foreach (SalesforceInstanceName salesforceInstanceName in (SalesforceInstanceName[])Enum.GetValues(typeof(SalesforceInstanceName))) { For<IGenericFormInitialValueResolver<SalesforceEditContactBlock>>() .Use<SalesforceEditFormInitialValueResolver>() .Ctor<SalesforceInstanceName>().Is(salesforceInstanceName) .Named(salesforceInstanceName.ToString()) // 按枚举值作为实例唯一标识 .LifecycleIs<HttpContextLifecycle>(); }
第二步:修改Factory获取逻辑,按名称匹配对应实例
var targetInstanceName = salesforceInstanceName ?? SalesforceInstanceName.Undefined; if (_iocContainer.TryGetInstance(actualType, targetInstanceName.ToString()) is IGenericFormInitialValueResolver returnValue) { return returnValue; }
解决方案二(上下文工厂方案,适配动态泛型场景)
如果需要适配多种泛型类型的IGenericFormInitialValueResolver<>,不需要逐个遍历枚举注册,改用上下文绑定的工厂注册即可:
// 注册时绑定HttpContext上下文取值逻辑 For<IGenericFormInitialValueResolver<SalesforceEditContactBlock>>() .LifecycleIs<HttpContextLifecycle>() .Use(context => { var instanceName = HttpContext.Current.Items["CurrentSalesforceInstance"] as SalesforceInstanceName? ?? SalesforceInstanceName.Undefined; return new SalesforceEditFormInitialValueResolver(instanceName); });
调用前先把当前请求对应的枚举值存入HttpContext.Items:
HttpContext.Current.Items["CurrentSalesforceInstance"] = salesforceInstanceName; var resolver = _iocContainer.TryGetInstance(actualType);
内容的提问来源于stack exchange,提问作者Tim Schmelter
相关产品推荐
相关产品推荐

