C# 温莎城堡-将解析参数传递给下层
我有一个web api项目,其中控制器依赖于某个存储层。例如。 每个控制器都有类似的代码:C# 温莎城堡-将解析参数传递给下层,c#,asp.net-web-api,inversion-of-control,castle-windsor,C#,Asp.net Web Api,Inversion Of Control,Castle Windsor,我有一个web api项目,其中控制器依赖于某个存储层。例如。 每个控制器都有类似的代码: public class ResourceController : ApiController { private readonly IResourceStorage _resourceStorage; private readonly IOtherStorage _otherStorage; public ResourceController(IResourceStorage
public class ResourceController : ApiController
{
private readonly IResourceStorage _resourceStorage;
private readonly IOtherStorage _otherStorage;
public ResourceController(IResourceStorage resourceStorage, IOtherStorage otherStorage)
{
_resourceStorage = resourceStorage;
_otherStorage = otherStorage;
}
// Web API Actions
}
存储的通用代码如下所示:
public class ResourceStorage : DBProvider, IResourceStorage
{
public ResourceStorage(string connectionString) : base(connectionString)
{
}
// storage methods
}
基于Web Api请求的某些特定条件,我需要能够将不同的连接字符串注入控制器的存储器。伪代码可能如下所示:
public class WindsorControllerActivator : IHttpControllerActivator
{
public IHttpController Create(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
string connectionString = ChooseDbConnectionStringBasedOnRequestContext(request);
var controller =
(IHttpController)_container.Resolve(connectionString, controllerType, new {databaseType = connectionString});
request.RegisterForDispose(
new Release(
() => _container.Release(controller)));
return controller;
}
}
我不知道如何以破坏性较小的方式将参数传递到存储器:)
我试过什么?备选方案:
您可以使用工厂模式: 然后简单地
我找到的解决方案是引入连接字符串提供程序:
public interface IConnectionStringProvider
{
string ConnectionString { get; }
}
使用工厂方法根据web请求注册此提供程序时:
kernel.Register(
Component.For(typeof (IConnectionStringProvider))
.ImplementedBy(typeof (ConnectionStringProvider))
.UsingFactoryMethod(
(k, context) =>
new ConnectionStringProvider(context.AdditionalArguments["connectionString"].ToString()))
.LifestylePerWebRequest());
在控制器激活器中,首先使用正确的参数解析连接字符串提供程序,然后解析控制器:
// The lifecycle of connection string provider if per web request.
// We resolve it first time with the correct parameters,
// so it is injected with the correct connection string throught the lifecycle of the request.
_container.Resolve<IConnectionStringProvider>(new {connectionString});
var controller =
(IHttpController) _container.Resolve(controllerType);
//连接字符串提供程序的生命周期(如果为每个web请求)。
//我们用正确的参数第一次解决它,
//因此,在请求的整个生命周期中,它都被注入了正确的连接字符串。
_Resolve(新的{connectionString});
无功控制器=
(IHTTP控制器)\ u容器解析(控制器类型);
它仍然不完美,看起来有点粗糙,但它允许保持对底层接口的依赖性,并且需要对我发现的解决方案中的代码库进行更少的更改可以肯定,它的侵入性要小得多。谢谢你的建议。我在这里仍然看到两个问题:1)必须为所有控制器提供额外的参数StorageFactory(它可以是通用的,但还有一个参数),2)必须在分配每个存储之前调用create,这也是一种侵入性的。我不会将你的答案标记为已被接受,并希望有人有一个更自然的解决方案,例如,工厂是否可以用于注射某种类型的电子注册注射?
kernel.Register(
Component.For(typeof (IConnectionStringProvider))
.ImplementedBy(typeof (ConnectionStringProvider))
.UsingFactoryMethod(
(k, context) =>
new ConnectionStringProvider(context.AdditionalArguments["connectionString"].ToString()))
.LifestylePerWebRequest());
// The lifecycle of connection string provider if per web request.
// We resolve it first time with the correct parameters,
// so it is injected with the correct connection string throught the lifecycle of the request.
_container.Resolve<IConnectionStringProvider>(new {connectionString});
var controller =
(IHttpController) _container.Resolve(controllerType);