我有一些类:X1 <- Y <- Z <- Config
(箭头表示通过构造函数注入)和X2 <- Y <- Z <- Config
。 Z
需要一些配置(Config
类),但是实例取决于最终类型:X1
和X2
(键入自身或以某种方式定义的键)。在此示例中,每个Y
,Z
和Config
类应该有两个不同的实例。
如何根据最终使用位置(Config
或Z
)在X1
中使用不同的X2
?
class X1
{
public X1(Y y)
{
int c = y.Z.Config.C; // This config variable is connected with X1.
}
}
class X2
{
public X2(Y y)
{
int c = y.Z.Config.C; // This config variable is different than the one for X1.
}
}
class Y
{
public Z Z { get; }
public Y(Z z)
{
Z = z;
}
}
class Z
{
public Config Config { get; }
public Z(Config config)
{
Config = config;
}
}
class Config
{
public int C { get; set; }
}
我可以像下面那样做,但是看起来很腥,很臭(一个粗糙的例子):
Bind<Config>().ToMethod(x =>
{
// Return proper config object depending on the classes found in the injection chain...
IRequest req = x.Request;
while (req != null)
{
if (req.Service.UnderlyingSystemType == typeof(X1))
{
return configForX1;
}
if (req.Service.UnderlyingSystemType == typeof(X2))
{
return configForX2;
}
req = req.ParentRequest;
}
throw new Exception("Oh no.");
});
或者要使其不那么腥:
class X1
{
public X1([Named("X1")] Config config, Y y)
{
y.SetConfig(config);
}
}
class Y
{
private readonly Z _z;
public Y(Z z)
{
_z = z;
}
public void SetConfig(Config config)
{
_z.SetConfig(config);
}
}
class Z
{
private Config _config;
public void SetConfig(Config config)
{
_config = config;
}
}
和
Bind<MetricsApiConfiguration>().To().Named("X1");
Bind<MetricsApiConfiguration>().To().Named("X2");
还有其他(更好的)主意吗?
WhenInjectedInto
已关闭,但是正如您所指出的,仅查看当前请求。我创建了扩展方法来解决这个确切的用例:
public static IBindingInNamedWithOrOnSyntax<T> WhenAnyAncestorIs<T>(this IBindingWhenSyntax<T> binding, params Type[] types)
{
bool Matches(IRequest request)
{
Type target = request.Target?.Member?.ReflectedType;
return (target != null && types.Any(t => t == target))
|| (request.ParentRequest != null && Matches(request.ParentRequest));
}
return binding.When(Matches);
}
并且使用类似:
Bind<IConfigSource>().To<DataConfigSource>()
.WhenAnyAncestorIs(
typeof(DataConfigurationRepository),
typeof(ManifestRepository),
typeof(DataManager)
)
.InSingletonScope();
对于不使用这些类型的请求,您将需要附加绑定。