I'm trying to implement automatic registration of my listeners to a singleton event aggregator when listeners are created by the IoC container - basically what Jeremy D. Miller is doing, but with Castle instead of StructureMap.
So I want to be able to "intercept" Windsor's object creation mechanism and, if the object supports the marker interface (let's say IListener), call the Subscribe method to an EventAggregator (which is also registered in the container) to make the newly created object a subscriber to events. Also, before the object instance has been released by the container, I want to be able to unsubscribe it.
I'm a little bit confused about what mechanism in Windsor Castle I should use to achieve something like this? I started looking at IInterceptor interface, but it seems to intercept all calls to the object, which is not what I really need (and want to avoid for performance reasons).
IKernel exposes various events like ComponentCreated and ComponentDestroyed which you can use to build that. There are many samples on the web.
Otherwise you could just use the event wiring facility, but it's not convention based.
You could also use OnCreate like this:
container.Register(
Component.For(typeof (Foo)).OnCreate(
(k, c) => {
// ...
eventAggregator.Subscribe(c);
// ...
}));
Related
I want to create a controller based JavaFX GUI consisting of multiple controllers.
The task I can't accomplish is to pass parameters from one Scene to another AND back.
Or in other words:
The MainController loads SubController's fxml, passes an object to SubController, switches the scene. There shall not be two open windows.
After it's work is done, the SubController shall then switch the scene back to the MainController and pass some object back.
This is where I fail.
This question is very similar to this one but still unanswered. Passing Parameters JavaFX FXML
It was also mentioned in the comments:
"This work when you pass parameter from first controller to second but how to pass parameter from second to first controller,i mean after first.fxml was loaded.
– Xlint Xms Sep 18 '17 at 23:15"
I used the first approach in the top answer of that thread.
Does anyone have a clue how to achieve this without external libs?
There are numerous ways to do this.
Here is one solution, which passes a Consumer to another controller. The other controller can invoke the consumer to accept the result once it has completed its work. The sample is based on the example code from an answer to the question that you linked.
public Stage showCustomerDialog(Customer customer) {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
Stage stage = new Stage(StageStyle.DECORATED);
stage.setScene(
new Scene(
(Pane) loader.load()
)
);
Consumer<CustomerInteractionResult> onComplete = result -> {
// update main screen based upon result.
};
CustomerDialogController controller =
loader.<CustomerDialogController>getController();
controller.initData(customer, onComplete);
stage.show();
return stage;
}
...
class CustomerDialogController() {
#FXML private Label customerName;
private Consumer<CustomerInteractionResult> onComplete
void initialize() {}
void initData(Customer customer, Consumer<CustomerInteractionResult> onComplete) {
customerName.setText(customer.getName());
this.onComplete = onComplete;
}
#FXML
void onSomeInteractionLikeCloseDialog(ActionEvent event) {
onComplete.accept(new CustomerInteractionResult(someDataGatheredByDialog));
}
}
Another way to do this is to add a result property to the controller of the dialog screen and interested invokers could listen to or retrieve the result property. A result property is how the in-built JavaFX dialogs work, so you would be essentially imitating some of that functionality.
If you have a lot of this passing back and forth stuff going on, a shared dependency injection model based on something like Gluon Ignite, might assist you.
I've used AfterBurner.fx for dependency injection, which is very slick and powerful as long as you follow the conventions. It's not necessarily an external lib if you just copy the 3 classes into your structure. Although you do need the javax Inject jar, so I guess it is an eternal reference.
Alternately, if you have a central "screen" from which most of your application branches out you could use property binding probably within a singleton pattern. There are some good articles on using singleton in JavaFX, like this one. I did that for a small application that works really great, but defining all of those bindings can get out of hand if there are a lot of properties.
To pass data back, the best approach is probably to fire custom Events, which the parent controller subscribes to with Node::addEventHandler. See How to emit and handle custom events? for context.
In complex cases when the two controllers have no reference to each other, a Event Bus as #jewelsea mentioned is the superior option.
For overall architecture, this Reddit comment provides some good detail: https://www.reddit.com/r/java/comments/7c4vhv/are_there_any_canonical_javafx_design_patterns/dpnsedh/
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 starting developing with Symfony2 framework and I like to use the Eventdispatcher. Now I have three questions I could find an answer with google yet.
Where I place the dispatcher so it is accessable from everywhere in
tha app?
How I can configure customevents? Should I place all in one file or
one for each bunble?
How much effort is it to configure it with annotations, i.e
#Event("some.event")? Is that possible?
General
I might suggest the Symfony 2 documentation on the EventDispatcher as a good starting point, assuming that you mean you wish to provide custom events rather than a custom event dispatcher.
Symfony2 Internals - The Event Dispatcher
Location of Events
In terms of location, an 'Event' folder within the appropriate bundle is a good choice. It is likely that the actual dispatching of the event will take place only within the bundle context, whereas listeners may reside elsewhere. This is however a separate topic and of minimal relevance as they simply subscribe to the event's string-name (e.g., 'store.order' to borrow the documentation's example) and only require knowledge of the Event's interface/type.
So you might have an Event called 'Foo' within the 'Bar' bundle in 'Zap' namespace:
namespace Zap\Bar\Event;
use Symfony\Component\EventDispatcher\Event;
class FooEvent extends Event
{
// ...
}
When you then come to dispatch an event from within your bundle, you might choose to use the event identifier 'zap.bar.foo', and of course you can then register listeners from elsewhere to be notified on this identifier as you see fit.
Accessing the Event Dispatcher
Where you wish to access the primary EventDispatcher instance, acquire access to the Dependency Injection Container and retrieve the 'event_dispatcher' service. A simple approach is to have your class extend 'ContainerAware' and then retrieve the dispatcher with
$dispatcher = $this->container->get('event_dispatcher');
To answer your first question:
Where I place the dispatcher so it is accessable from everywhere in tha app?
Actually, there is already preconfigured event dispatcher service accessible, as #jstephenson pointed out, by calling $dispatcher = $this->container->get('event_dispatcher'); so you don't have to create your own instance anywhere.
However, if you need your own event dispatcher, you can simply configure it in your services configuration file (i.e. services.xml) of your bundle like this:
<service id="my_dispatcher" class="Symfony\Component\EventDispatcher\EventDispatcher" />
You can of course use your own dispatcher class as long as it implements EventDispatcherInterface.
What exactly will this addActionListener Do.....we we call button.addActionListener(this) what will happen
It basically adds this (the current object) to a list of objects that will be notified when the component has an action performed on it, such as a button being pressed.
It's a way of registering your interest in what is happening to the component and is useful in that you don't have to keep polling a component to check its status.
Your object (or class, really) simply implements the interface methods for listening (such as actionPerformed) and that method will be called for each event that happens.
The Java tutorials have a large variety of different articles on the various listeners that you're likely to use.
I am fond of using decorator chains instead of inheritance, and as long as my services have Singleton or Transient lifestyles (and their dependencies are scoped in the same manner) this works perfectly. I've started to use the TypedFactoryFacility to generate factories for services which require some sort of input which can not be resolved through the ioc container. My headache starts when something deep in the decorator chain requires a factory and Windsor refuses to pass inline dependencies down the inheritance chain. As I understand this is by design, but I don't agree that this breaks encapsulation when you are using a factory which explicitly states what you need to produce the output (I think Windsor should pass inline dependencies to components which are factory resolvable, but I'm guessing its not that straight forward. Anyway, at the end of the day I end up exposing my decorator chain like this:
public ISessionInputOutput Create(Session session)
{
IServerInput baseInput = _inputFactory.GetBaseInput(session.CommunicationSocketStream);
IServerInput threadSafeInput = _inputFactory.GetThreadSafeInput(baseInput);
IServerOutput output = _outputFactory.Create(session.CommunicationSocketStream);
ISessionInputOutput baseIO = _sessionIOFactory.GetBaseIO(baseInput, output);
ISessionInputOutput commandHandlerIO = _sessionIOFactory.GetCommandHandlerIO(baseIO, session);
ISessionInputOutput errorHandlingIO = _sessionIOFactory.GetErrorHandlingIO(commandHandlerIO, session);
_releaseInfo.Add(errorHandlingIO, new CreatedIOInformation(baseInput, threadSafeInput, output, baseIO, commandHandlerIO));
return errorHandlingIO;
}
In the example I am using 3 factory proxies, and manually combine the output to produce the decorator chain.
I can't simply use ServiceOverrides as I usually do to introduce new services. This doesn't feel right and I am hoping that someone can suggest a better solution what I've used above.
I've also tried to solve this by using child containers, but this introduces a bit more ioc details into the stack than I like.
If you really feel you need to enable passing down the dependencies you can enable that by overriding RebuildContextForParameter method in DefaultDependencyResolver and passing true for propagateInlineDependencies.
Be aware that this is a double-edged sword. You can also filter this out and enable this behavior only when you're resolving one of the few services for which you need this, and stick to the default behavior for all other.