Reputation: 1104
I'm using Web Api with the OWIN pipeline.
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);
}
}
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IMyClass>().ImplementedBy<MyClass>()
.LifeStyle.PerWebRequest()
.DependsOn(new {
configSetting = ConfigurationManager.AppSettings["key"],
otherSetting = ???
}));
}
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();
}
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
}
}
Here's where I'm stuck. Whenever an instance of MyClass is resolved the value of otherSetting needs to be assigned.
The value of otherSetting is determined by two things.
1) The client_id claims value from the request.
2) An async call to a method that takes the client_id as a parameter and returns a string value. Which is what gets set into otherSetting
public async Task<string> GetOtherSetting(string client_id) {
return "value";
}
I'm not sure where to even begin to get Castle to inject a value based on those two criteria...
UPDATE: I've updated to potatopeelings answer with some minor changes and it seems to be working fine.
.DynamicParameters(async (k, p) =>
{
var fundNameProvider = k.Resolve<IFundNameValueProvider>();
p["otherSetting"] = await fundNameProvider.GetFundNameAsync();
k.ReleaseComponent(fundNameProvider);
}))
I changed it to an async lambda so I can await the method. I also called ReleaseComponent as I was under the impression that objects you manually Resolved with Castle you also needed to manually release.
Upvotes: 0
Views: 925
Reputation: 41065
Use UsingFactoryMethod
and DynamicParamters
First, inject the current claims
...
Component.For<ClaimsIdentity>().UsingFactoryMethod(() => HttpContext.Current.User.Identity as ClaimsIdentity).LifestylePerWebRequest()
...
into a service (IOtherValueProvider
- PerWebRequest) that has a GetOtherSetting
method to wait on an async call (i.e. convert the async call to a synchronous call) to get otherSetting from the client_id extracted from the injected ClaimsIdentity
Then use DynamicParameters
to get the value
... register your class ...
.DynamicParameters((kernel, parameters) =>
{
parameters["otherSetting"] = kernel.Resolve<IOtherValueProvider>().GetOtherSetting();
}))
Upvotes: 1