相同接口的 StructureMap 但具有不同构造函数参数的多个实例
StructureMap for same interface but with multiple instances for different constructor parameters
我正在为 StructureMap 苦苦挣扎。我需要确保每个 HttpContextLifecycle
获得一个实例,但每个构造函数参数获得一个实例。我们原来的工作代码是:
注册表:
For<IGenericFormInitialValueResolver<SalesforceEditContactBlock>>()
.LifecycleIs<HttpContextLifecycle>()
.Use<SalesforceEditFormInitialValueResolver>();
In FormInitialValueResolverFactory
(actualType 是 IGenericFormInitialValueResolver
通用类型):
if (_iocContainer.TryGetInstance(actualType) is IGenericFormInitialValueResolver returnValue)
{
if (returnValue is ISalesforceInstanceFormInitialValueResolver salesforceInstanceFormInitialValueResolver &&
salesforceInstanceName.HasValue)
{
salesforceInstanceFormInitialValueResolver.SalesforceInstanceName = salesforceInstanceName.Value;
}
return returnValue;
}
现在我需要更改它,以便在构造函数中给出 SalesforceInstanceName
。但我仍然希望为每个 SalesforceInstanceName
(它是一个具有 2 个值的枚举)实例缓存 HttpContextLifecycle
。所以我通过 TryGetInstance
重载传递了参数:
ExplicitArguments args = new ExplicitArguments();
args.Set(salesforceInstanceName ?? SalesforceInstanceName.Undefined);
if (_iocContainer.TryGetInstance(actualType, args) is IGenericFormInitialValueResolver returnValue)
{
return returnValue;
}
它的工作方式是我得到了实例,但总是一个新实例,所以它不会在每个 http 生命周期中缓存。
所以我尝试更改注册表:
foreach (SalesforceInstanceName salesforceInstanceName in (SalesforceInstanceName[])Enum.GetValues(typeof(SalesforceInstanceName)))
{
For<IGenericFormInitialValueResolver<SalesforceEditContactBlock>>()
.Add<SalesforceEditFormInitialValueResolver>().Ctor<SalesforceInstanceName>()
.Is(salesforceInstanceName)
.LifecycleIs<HttpContextLifecycle>();
}
但是现在TryGetInstance
总是returnsnull
.
如果您通过 ExplicitArguments
传递自定义构造函数参数,StructureMap 将始终构建一个新实例。您可能想像这样使用命名实例:
foreach (SalesforceInstanceName salesforceInstanceName in (SalesforceInstanceName[])Enum.GetValues(typeof(SalesforceInstanceName)))
{
For<IGenericFormInitialValueResolver<SalesforceEditContactBlock>>()
.Use<SalesforceEditFormInitialValueResolver>()
.Ctor<SalesforceInstanceName>()
.Is(salesforceInstanceName)
.Named(salesforceInstanceName.ToString())
.LifecycleIs<HttpContextLifecycle>();
}
你基本上是说,对于 SalesforceInstanceName
枚举的每个值,你都注册了 SalesforceEditFormInitialValueResolver
的单独命名实例(具有所述枚举值的名称),并将该枚举值作为构造函数参数。
然后解析,而不是使用ExplicitArguments
,使用名称:
container.TryGetInstance(actualType, salesforceInstanceName.ToString());
在看到 (我现在将检查)之前,我已经有了一个可行的解决方案:
IGenericFormInitialValueResolver genericFormResolver = _iocContainer.GetAllInstances(actualType)
.OfType<IGenericFormInitialValueResolver>()
.FirstOrDefault(resolver => resolver is ISalesforceInstanceFormInitialValueResolver sr && sr.SalesforceInstanceName == salesforceInstanceName);
if (genericFormResolver != null)
{
return genericFormResolver;
}
所以我正在使用 iocContainer.GetAllInstances
获取所有 (3) 个实例,然后过滤我需要的那个。我想 Evk 的方法更简洁,我可能更有效率。
更新:我测试了 Evk 的方法,它运行良好。我总是为每个 SalesforceInstanceName
得到一个缓存实例,它比我的更好的是:只构建所需的实例而不是全部。我保留这个答案以防有人需要替代方案。
我正在为 StructureMap 苦苦挣扎。我需要确保每个 HttpContextLifecycle
获得一个实例,但每个构造函数参数获得一个实例。我们原来的工作代码是:
注册表:
For<IGenericFormInitialValueResolver<SalesforceEditContactBlock>>()
.LifecycleIs<HttpContextLifecycle>()
.Use<SalesforceEditFormInitialValueResolver>();
In FormInitialValueResolverFactory
(actualType 是 IGenericFormInitialValueResolver
通用类型):
if (_iocContainer.TryGetInstance(actualType) is IGenericFormInitialValueResolver returnValue)
{
if (returnValue is ISalesforceInstanceFormInitialValueResolver salesforceInstanceFormInitialValueResolver &&
salesforceInstanceName.HasValue)
{
salesforceInstanceFormInitialValueResolver.SalesforceInstanceName = salesforceInstanceName.Value;
}
return returnValue;
}
现在我需要更改它,以便在构造函数中给出 SalesforceInstanceName
。但我仍然希望为每个 SalesforceInstanceName
(它是一个具有 2 个值的枚举)实例缓存 HttpContextLifecycle
。所以我通过 TryGetInstance
重载传递了参数:
ExplicitArguments args = new ExplicitArguments();
args.Set(salesforceInstanceName ?? SalesforceInstanceName.Undefined);
if (_iocContainer.TryGetInstance(actualType, args) is IGenericFormInitialValueResolver returnValue)
{
return returnValue;
}
它的工作方式是我得到了实例,但总是一个新实例,所以它不会在每个 http 生命周期中缓存。
所以我尝试更改注册表:
foreach (SalesforceInstanceName salesforceInstanceName in (SalesforceInstanceName[])Enum.GetValues(typeof(SalesforceInstanceName)))
{
For<IGenericFormInitialValueResolver<SalesforceEditContactBlock>>()
.Add<SalesforceEditFormInitialValueResolver>().Ctor<SalesforceInstanceName>()
.Is(salesforceInstanceName)
.LifecycleIs<HttpContextLifecycle>();
}
但是现在TryGetInstance
总是returnsnull
.
如果您通过 ExplicitArguments
传递自定义构造函数参数,StructureMap 将始终构建一个新实例。您可能想像这样使用命名实例:
foreach (SalesforceInstanceName salesforceInstanceName in (SalesforceInstanceName[])Enum.GetValues(typeof(SalesforceInstanceName)))
{
For<IGenericFormInitialValueResolver<SalesforceEditContactBlock>>()
.Use<SalesforceEditFormInitialValueResolver>()
.Ctor<SalesforceInstanceName>()
.Is(salesforceInstanceName)
.Named(salesforceInstanceName.ToString())
.LifecycleIs<HttpContextLifecycle>();
}
你基本上是说,对于 SalesforceInstanceName
枚举的每个值,你都注册了 SalesforceEditFormInitialValueResolver
的单独命名实例(具有所述枚举值的名称),并将该枚举值作为构造函数参数。
然后解析,而不是使用ExplicitArguments
,使用名称:
container.TryGetInstance(actualType, salesforceInstanceName.ToString());
在看到
IGenericFormInitialValueResolver genericFormResolver = _iocContainer.GetAllInstances(actualType)
.OfType<IGenericFormInitialValueResolver>()
.FirstOrDefault(resolver => resolver is ISalesforceInstanceFormInitialValueResolver sr && sr.SalesforceInstanceName == salesforceInstanceName);
if (genericFormResolver != null)
{
return genericFormResolver;
}
所以我正在使用 iocContainer.GetAllInstances
获取所有 (3) 个实例,然后过滤我需要的那个。我想 Evk 的方法更简洁,我可能更有效率。
更新:我测试了 Evk 的方法,它运行良好。我总是为每个 SalesforceInstanceName
得到一个缓存实例,它比我的更好的是:只构建所需的实例而不是全部。我保留这个答案以防有人需要替代方案。