如何解决Castle Windsor依赖HttpRequestMessage值的实例

时间:2017-05-18 23:18:42

标签: c# dependency-injection castle-windsor

我使用Web Api和OWIN管道。

Startup.cs

public class Startup {
    public void Configuration(IAppBuilder app) {
        var container = new WindsorContainer().Install(FromAssembly.This());

        var config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();

        // extension method to resolve controllers with Windsor.
        app.UseWindsorApi(config, container);
    }
}

MyClassInstaller.cs(IWindsorInstaller)

public void Install(IWindsorContainer container, IConfigurationStore store) 
{
    container.Register(
        Component.For<IMyClass>().ImplementedBy<MyClass>()
            .LifeStyle.PerWebRequest()
            .DependsOn(new {
                configSetting = ConfigurationManager.AppSettings["key"],
                otherSetting = ???
            }));
}

MyClass.cs&amp; IMyClass.cs

public class MyClass : IMyClass {
    private readonly string configSetting;
    private readonly string otherSetting;

    public MyClass(string configSetting, string otherSetting) {
        this.configSetting = configSetting;
        this.otherSetting = otherSetting;
    }

    public void DoSomething() {
        // method that uses the settings that were set in the constructor.
    }
}

public interface IMyClass {
    void DoSomething();
}

MyController.cs

public class MyController : ApiController {
    private readonly IMyClass myClass;

    public MyController(IMyClass myClass) {
        this.myClass = myClass;
    }

    [HttpGet]
    [Route("")]
    public async Task<IHttpActionResult> GetAsync() {
        // uses this.myClass
    }
}

在这里,我被困住了。每当解析 MyClass 的实例时,都需要分配 otherSetting 的值。

otherSetting 的值由两件事决定 1)来自请求的 client_id 声明值 2)对方法的异步调用,该方法将 client_id 作为参数并返回字符串值。哪个被设置为 otherSetting

public async Task<string> GetOtherSetting(string client_id) {
    return "value";
}

我不确定在哪里开始让Castle根据这两个标准注入一个值......

更新 我已经更新到potatopeelings回答了一些小的改动,似乎工作正常。

.DynamicParameters(async (k, p) =>
{
    var fundNameProvider = k.Resolve<IFundNameValueProvider>();
    p["otherSetting"] = await fundNameProvider.GetFundNameAsync();
    k.ReleaseComponent(fundNameProvider);
}))

我把它改成了异步lambda,所以我可以等待这个方法。 我也称为ReleaseComponent,因为我认为手动解决了Castle的对象也需要手动释放。

1 个答案:

答案 0 :(得分:1)

使用UsingFactoryMethodDynamicParamters

首先,注入当前的索赔

...
Component.For<ClaimsIdentity>().UsingFactoryMethod(() => HttpContext.Current.User.Identity as ClaimsIdentity).LifestylePerWebRequest()
...

进入一个服务(IOtherValueProvider - PerWebRequest),它有GetOtherSetting方法等待异步调用(即将异步调用转换为同步调用)以获得 otherSetting 从注入的ClaimsIdentity

中提取的 client_id

然后使用DynamicParameters获取值

... register your class ...
.DynamicParameters((kernel, parameters) =>
    {
        parameters["otherSetting"] = kernel.Resolve<IOtherValueProvider>().GetOtherSetting();
    }))