I am trying to use a component that requires a start method be called after the object is constructed. I tried using the startable facility for castle for this but the start method in this component takes some arguments. Is there a way I can supply arguments to the method called by the startable facility in castle? Or is there another way of doing this (short of calling the method myself)?
I cannot modify the component I am using.
Related
I've a View and Utility classes and wanted to hook-in the Utility method once View's job is done. So wanted to call the utility method (to add behavior to the view) once View's render call is done.
Using ES6 Proxy API, Is there a way to execute a method before / after executing the main method ? (aka method interceptions)
Similar to YUI3 Do API.
http://yuilibrary.com/yui/docs/api/classes/Do.html
Yes there is a way. Actually I'm trying to build the same thing and as long as you use a synchronous context I already got it working. Have a look at the code examples in the issue I created for my problem: stack overflow when returning an ES6 proxy through a promise
What you need to do to intercept the call is to use the ES6 proxy to get notified of the get-call that takes place to retrieve the function before the method is actually called.
In my example you can see that you get all the information about the call like what method was called with which parameters and also who called it and on which target it was originally called.
I've been running into endless problems attempting to use Windsor with Web API and injecting HttpRequestMessage into downstream dependencies of a controller. Since I've tried all the matching answers on Stackoverflow, I'd like to ask the question in a different way:
In Castle Windsor, how can I resolve a component instance while supplying a value for a downstream dependency? That is, the supplied value is required by a component that is required by the component being resolved.
For context, I'm trying to inject HttpRequestMessage so that I can use it to resolve the request context (primarily to resolve an absolute URL).
Edit I'd also like to point out that I don't currently have a dependency on Web Host / System.Web and I'd rather not change that.
A proper approach is to
Create IMyDesiredRouteParameterProvider
Implement it. Get the current request inside it and get the url
Register it and inject it in the desired dependent class via constructor.
I made myself such an implementation and I can say that this way it works fine. You can make Web.Infrastructure assembly and put the implementation there. Or put both the interface and the implementation there if you are going to reference it from another web module.
using System;
using System.Web;
namespace RouteParameterProvider
{
interface IMyRouteParameterProvider
{
string GetRouteParameter();
}
public class ControllerActionMethodRouteParameterProvider : IMyRouteParameterProvider
{
public string GetRouteParameter()
{
string Parameter = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"] as string;
if (string.IsNullOrEmpty(Parameter))
{
throw new InvalidOperationException();
}
return Parameter;
}
}
}
You can get every possible thing that the Request Context contains from :
HttpContext.Current.Request.RequestContext
And it will be better if you rethink your design decision :
I need HttpRequestMessage to be regstered prior to creating each
instance of SomethingController so that it will be available down at
the LinkGenerator layer.
Containers are to be initialized at runtime and then used to resolve.
I need HttpRequestMessage to be regstered prior to creating each
instance of SomethingController so that it will be available down at
the LinkGenerator layer.
It sounds like you want to register an item with the container at runtime, post-startup. In general, this is not a good practice--registration should be a discrete event that happens when the app is fired up, and the container's state should not be changed during runtime.
Dependency Injection is about resolving service components, not runtime state--state is generally passed via methods (method injection). In this case it sounds like your LinkGenerator component needs access to the ambient state of the request.
I'm not that familiar with HttpRequestMessage, but this answer seems to show that it is possible to retreive it from HttpContext.Current. You could make this a method on your LinkGenerator class, or wrap this call in a separate component that gets injected into LinkGenerator (HttpRequestMessageProvider?). The latter would be my preferred method, as it allows LinkGenerator to be more testable.
Given the lack of a clean way of doing this and Web API not providing information as to the hosted endpoint beyond per-request context objects, I ended up injecting the base url from configuration.
Is this library by Mark Seemann the answer? In the description he writes explicitly :
This approach enables the use of Dependency Injection (DI) because the
request can be injected into the services which require it.
Then gives an example :
// Inside an ApiController
var uri = this.Url.GetLink(a=> a.GetById(1337));
By which you can then pass the URL down the road in the service that you have injected in the controller.
UPDATE :
Mark Seemann wrote about the same exact problem here:
"Because HttpRequestMessage provides the context you may need to
compose dependency graphs, the best extensibility point is the
extensibility point which provides an HttpRequestMessage every time a
graph should be composed. This extensibility point is the
IHttpControllerActivator interface:..."
This way you can pass request context information to a component deep in the object graph by getting from the HttpRequestMessage and passing it to the DI container.
Just take a look at the interface of IHttpControllerActivator.
The WEB API framework gets the IHttpControllerActivator through DependencyResolver. You probably already replaced it by your CastleWindsorDependencyResolver. Now you have to implement and register your HttpControllerActivator and register it.
When the WEB API framework gets IHttpControllerActivator from DependencyResolver (your Castle Windsor DR) and calls IHttpControllerActivator.Create() it will pass you the HttpRequestMessage. You can get your info from there and pass it to the your CastleDR before you call Resolve(typeof(MyController)) which will resolve the whole object graph - that means you will have MyHttpContextInfo to inject in your XYZComponent deep in the resolution stack.
This way tou are passing the arguments in the last possible moment but it is still possible. In Castle Windsor I make such passing of arguments though CreationContext.AdditionalArguments["myArgument"];.
I am trying to register all of my typed factories in Castle Windsor using a single registration. All of my factories implement IModelFactory so I would like to be able to write something like:
container.Register(Types.FromThisAssembly()
.BasedOn<IModelFactory>()
.AsFactory());
The BasedOn method returns a type BasedOnDescriptor which does not allow me to call the AsFactory() extension method.
Do I really need to register all typed factories one by one?
.Configure(x => x.AsFactory());
Using Castle Windsor I can register multiple implementations of a type e.g.
container.Register(Component.For<IMyInterceptor>()
.ImplementedBy<MyInterceptor>();
container.Register(Component.For<IMyInterceptor>()
.ImplementedBy<MyInterceptor2>();
This all works as you'd expect and I can resolve multiple implementations using ResolveAll()
If I try to register an instance of another implementation at runtime though - e.g.
var interceptor = new MyInterceptor3();
Container.Register(
Component.For<IMyInterceptor>()
.Instance(interceptor));
I get an exception:
There is a component already registered for the given key MyInterceptor3
Is this the expected behaviour? What I'm trying to acheive is to use e.g. Container.ResolveAll() to get a list of default implementations of IMyInterceptor plus optional additional implementations (i.e. on a request by request basis, when debug modes are enabled).
This will sort you out.
var interceptor = new MyInterceptor3();
Container.Register(
Component.For<IMyInterceptor>()
.Instance(interceptor).Named("something unique));
Names must be unique.
is it already possible to use Bound lifestyle (new lifestyles in castle) in xml configuration? Does anyone have some expirience with it?
Officially it is not.
However, although discouraged (as is using XML configuration in general), it is possible.
In order for this to work you will need to, in addition to setting lifestyle to bound, specify scopeRootBinderType attribute.
Its value should be name of a type that should be used as your scope binder (i.e. figuring out which other component your scoped component should be bound to).
The scope binder type needs to have a public default constructor and a method that takes IHandler[] and returns a single IHandler (that is it has to match the signature of the delegate that you can pass when you specify bound lifestyle via registration API in code).