Configuring Castle Windsor using xml/app.config - castle-windsor

I am currently building a sample application using Castle Windsor. The motto is to use xml/app.config to switch method interception on/off. I had used the Fluent API earlier and it worked as a charm. As the next step, I am trying to replace the fluent API with my xml.
The gist of the code is as follows:
A class called RandomOperations with two virtual methods.
A LoggingAspect class which implements IInterceptor.
A MyInterceptorsSelector class which implements IModelInterceptorsSelector
A Program.cs which had the fluent api syntax earlier and is now uses to only make calls to methods of RandomOperations class.
An app.config with a section called which has the xml syntax of registering components.
When I use the fluent api, I am able to intercept the method calls but I am unable to do it using the xml/app.config registration. Could someone please throw some light on what is being missed?
The classes are as follows:
RandomOperations.cs
public class RandomOperations
{
public virtual int MyRandomMethod(int x)
{
return x * x;
}
public virtual void Writer(string x)
{
Console.WriteLine(x);
}
}
LoggingAspect.cs
public class LoggingAspect : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("Intercepted the call to " + invocation.Method.Name);
invocation.Proceed();
Console.WriteLine("After the method call, the return value is " + invocation.ReturnValue);
}
}
MyInterceptorsSelector.cs
public class MyInterceptorsSelector : IModelInterceptorsSelector
{
public bool HasInterceptors(ComponentModel model)
{
return typeof(LoggingAspect) != model.Implementation &&
model.Implementation.Namespace.StartsWith("ConsoleApplication1") ;
}
public InterceptorReference[] SelectInterceptors(ComponentModel model, Castle.Core.InterceptorReference[] obj)
{
var interceptors = new List<InterceptorReference>(model.Interceptors.Count + 1);
foreach (InterceptorReference inter in model.Interceptors)
{
interceptors.Add(inter);
}
return interceptors.ToArray();
}
}
Main in Program.cs
static void Main(string[] args)
{
var container = new WindsorContainer();
//container.Register(Component.For<RandomOperations>().Interceptors(typeof(LoggingAspect)));
//container.Register(Component.For<LoggingAspect>());
//container.Kernel.ProxyFactory.AddInterceptorSelector(new MyInterceptorsSelector());
var service = container.Resolve<RandomOperations>();
service.MyRandomMethod(4);
service.Writer("Hello, World");
}
Removing the commented out fluent api syntax makes the application work correctly.
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
</configSections>
<castle>
<components>
<component id="MyInterceptorsSelector" type="MyInterceptorsSelector"/>
<component
id="LoggingAspect"
type="ConsoleApplication1.LoggingAspect, ConsoleApplication1">
</component>
<component
type="ConsoleApplication1.RandomOperations, ConsoleApplication1">
<interceptors selector="${MyInterceptorsSelector}">
<interceptor>${LoggingAspect}</interceptor>
</interceptors>
</component>
</components>
</castle>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
Thanks in advance.

You need to pass an IConfigurationInterpreter to your Windsor constructor. Change:
var container = new WindsorContainer();
To:
var container = new WindsorContainer(new XmlInterpreter());
The XmlInterpreter (with no parameters) will pull configuration from your app.config/web.config.
For more options on using IConfigurationInterpreter, see the docs.

Related

Windsor, inject container in class

Hi have the following component registered into Castle Windsor:
public class CommandDispatcher : IServiceCommandDispatcher
{
private readonly IWindsorContainer container;
public CommandDispatcher(IWindsorContainer container)
{
this.container = container;
}
#region IServiceCommandDispatcher Members
public void Dispatch<TCommand>(TCommand command) where TCommand : IServiceCommand
{
var handler = container.Resolve<IServiceCommandHandler<TCommand>>();
handler.Handle(command);
}
#endregion
}
And the dispatcher is registered in the following way:
Component
.For<IServiceCommandDispatcher>()
.ImplementedBy<CommandDispatcher>(),
But the field container is null when I resolve an instance of the dispatcher.
What should I do in order to pass the container to the resolved children items?
Windsor solves this problem for you with the Typed Factory Facility.
In the below example I want the implementation of ICommandHandlerFactory to resolve my command handler from my windsor container.
class CommandDispatcher : IServiceCommandDispatcher
{
private readonly ICommandHandlerFactory factory;
public CommandDispatcher(ICommandHandlerFactory factory)
{
this.factory = factory;
}
public void Dispatch<T>(T command) where T : IServiceCommand
{
var handler = this.factory.Create(command);
handler.Handle(command);
this.factory.Destroy(handler);
}
}
To achieve this I only need to create the ICommandHandlerFactory Interface.
public interface ICommandHandlerFactory
{
Handles<T> Create<T>(T command) where T : IServiceCommand;
void Destroy(object handler);
}
No implementation of ICommandHandlerFactory is required as Windsor will create the implementation. Windsor uses the convention that a method that returns an object is a resolve method and a method that returns void is a release method.
To register the factory you need to include using Castle.Facilities.TypedFactory and then register your factory as follows
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<ICommandHandlerFactory>()
.AsFactory()
);
Just to reiterate you do not have to write any implementation code for your factory.
This works:
container.Register(Component.For<IWindsorContainer>().Instance(container));
It's not ideal, because you still have to call the Resolve method. There may be a better way to do this, using a factory. This looks similar to what you're trying to do:
http://kozmic.net/2010/03/11/advanced-castle-windsor-ndash-generic-typed-factories-auto-release-and-more/

Castle Windsor and WCF Web Api Message Handlers

I'm trying to use Castle Windsor to create my message handlers because just using ...
MessageHandlers.Add(typeof(MyHandler));
... doesn't allow me to use constructor injection of other services, for example a logger
So, I've create an installer which registers all my handlers (of which there is currently one!)
public class MessageHandlerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
AllTypes
.FromThisAssembly()
.Where(t => t.IsSubclassOf(typeof (DelegatingHandler)))
.Configure(c => c.LifeStyle.Custom(InstallerContext.LifestyleManager))
);
}
}
This works fine, when I run it through the debugger I can see the extra component registration in the container.
But when I try to set up the message handler factory for WCF Web Api it doesn't appear to work. (I have breakpoints in the SendAsync method which never gets hit)
public class MyApiConfiguration : WebApiConfiguration
{
public MyApiConfiguration(IWindsorContainer container)
{
EnableTestClient = true;
IncludeExceptionDetail = true;
CreateInstance = ((serviceType, context, request) => container.Resolve(serviceType));
ErrorHandlers = (handlers, endpoint, description) => handlers.Add(container.Resolve<GlobalErrorHandler>());
MessageHandlerFactory = () => container.ResolveAll<DelegatingHandler>();
}
}
So, I'm obviously missing something. I just don't know what it is. Can anyone enlighten me?
EDIT (extra config code, as requested)
public void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
AddServiceRoutes(routes);
}
private static void AddServiceRoutes(RouteCollection routes)
{
Container = WindsorContainerBootStrap.CreateContainerAndInstallComponents<PerThreadLifestyleManager>();
var config = new EtailApiConfiguration(Container);
routes.MapServiceRoute<CustomersApi>("customer", config);
routes.MapServiceRoute<ConsumerApi>("consumer", config);
routes.MapServiceRoute<PricePlansApi>("priceplans", config);
}
EDIT 2 (The Solution)
I had a constructor to my Handler like so ...
public MyHandler(DelegatingHandler innerChannel, ILogger logger)
: base(innerChannel)
{
_logger = logger;
}
... that wasn't getting called despite the changing the init code to use a lambda ...
MessageHandlerFactory = () => container.ResolveAll<DelegatingHandler>();
... so I added another constructor which just takes an ILogger and all is well. I figured that my container didn't know what a Delegating Handler was and that the MessageHandlerFactory must be dealing with that somehow.
You need to use the lambda for ctor injection, that is why it is there. BTW, you are missing a ()
How are you registering your routes, are you passing in the configuration object?

GWT RCP ServiceEntryPointSpecifiedException

Sry I am newbie to this Topic, but I always get this Exception when I want to make a rpc call:
Caused by: com.google.gwt.user.client.rpc.ServiceDefTarget$NoServiceEntryPointSpecifiedException: Service implementation URL not specified
I don't know why, because I have make it like the gwt Tutorial.
Thats my source code:
web.xml:
<web-app>
<servlet>
<servlet-name>SpeicherService</servlet-name>
<servlet-class>de.fhdo.kuss.server.SpeicherServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SpeicherService</servlet-name>
<url-pattern>/SpeicherService</url-pattern>
</servlet-mapping>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>Kuss_Projekt.html</welcome-file>
</welcome-file-list>
</web-app>
-
Kuss_Projekt.gwt.xml:
<module rename-to='kuss_projekt'>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User' />
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean' />
<!--<inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!--<inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<!-- Other module inherits -->
<!-- Specify the app entry point class. -->
<entry-point class='de.fhdo.kuss.client.Kuss_Projekt' />
<!-- Specify the paths for translatable code -->
<source path='client' />
<source path='shared' />
</module>
-
Speicherservice:
#RemoteServiceRelativePath("SpeicherService")
public interface SpeicherService extends RemoteService {
String getName(String name);
public static class Util {
private static SpeicherServiceAsync instance;
public static SpeicherServiceAsync getInstance(){
if (instance == null) {
instance = GWT.create(SpeicherService.class);
}
return instance;
}
}
}
-
SpeicherServiceAsync:
public interface SpeicherServiceAsync {
void getName(String name, AsyncCallback<String> callback);
}
-
SpeicherServiceImpl:
public class SpeicherServiceImpl extends RemoteServiceServlet implements SpeicherService {
#Override
public String getName(String name) {
return("Server meldet sich " + name);
}
}
-
Test():
public void test() {
AsyncCallback<String> callback = new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
#Override
public void onSuccess(String result) {
Window.alert(result);
}
};
SpeicherService.Util.getInstance().getName("test",callback);
}
Add back in:
#RemoteServiceRelativePath("SpeicherService")
Then in your web.xml replace
<url-pattern>/SpeicherService</url-pattern>
with
<url-pattern>/kuss_projekt/SpeicherService</url-pattern>
The reason you need to do that is because you are using: <module rename-to='kuss_projekt'> in your gwt.xml.

Constructor injection issue

When MainClass is created public MyWindsorClass(IMyInterface obj) {} is called and when MainClass2 is created public MyWindsorClass(IMyInterface obj) {} is also called when I'm expecting public MyWindsorClass() {} to be called. What exactly am I doing wrong?I'm having an issue with constructor injection. Here is an example:
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer(new XmlInterpreter());
var objs = container.ResolveAll<IMyWindsorInterface>();
}
}
public interface IMyWindsorInterface { }
public class MyWindsorClass : IMyWindsorInterface
{
public MyWindsorClass() {}
public MyWindsorClass(IMyInterface obj) {}
}
public interface IMyInterface { }
public class MyInjectedClass : IMyInterface{ }
<castle>
<components>
<component id="MainClass"
service="CastleTest.IMyWindsorInterface, CastleTest"
type="CastleTest.MyWindsorClass, CastleTest"
inspectionBehavior="None"
lifestyle="Transient">
<parameters>
<obj>${blah}</obj>
</parameters>
</component>
<component id="MainClass2"
service="CastleTest.IMyWindsorInterface, CastleTest"
type="CastleTest.MyWindsorClass, CastleTest"
inspectionBehavior="None"
lifestyle="Transient" />
<component id="blah"
service="CastleTest.IMyInterface, CastleTest"
type="CastleTest.MyInjectedClass, CastleTest"
inspectionBehavior="None"/>
</components>
</castle>
When MainClass is created public MyWindsorClass(IMyInterface obj) {} is called and when MainClass2 is created public MyWindsorClass(IMyInterface obj) {} is also called when I'm expecting public MyWindsorClass() {} to be called. What exactly am I doing wrong? Thanks to anyone that can help!
Windsor will by default autowire all available dependencies. In your case, IMyInterface is available as a component so Windsor will choose the constructor that can satisfy the most dependencies.
You may change this behavior ad-hoc by removing the constructor from the component model so Windsor doesn't 'see' it any more:
var container = new WindsorContainer();
container.Kernel.ComponentModelCreated += model => {
if (model.Name == "MainClass2")
model.Constructors.Remove(model.Constructors.First(c => c.Dependencies.Any(m => m.TargetType == typeof(IMyInterface))));
};
container.Install(Configuration.FromAppConfig());

Castle Windsor: Set component dependencies on existing object

In MEF it's possible to set the dependencies for an existing object using something like:
container.SatisfyImportsOnce(instance);
Is it possible to do the same with Castle Windsor?
I'm using (read: learning) Caliburn.Micro, and trying to update the template project from MEF to Windsor, which is where I've come across the issue.
Sorry Neil, Windsor doesn't have that feature
Castle Windsor FAQ
Windsor will resolve a property dependency (which it considers an optional dependency) such as an ILogger property if there is a registered component for that service. But this only happens during component activation...when the component is constructed the first time, there is no way to pass Windsor an existing instance and inject components into properties.
With Castle Windsor you can register an existing instance with the container, is this the kind of thing you are looking for?
var instance = new Logger();
var container = new WindsorContainer();
container.Register(Component.For<ILogger>().Instance(instance))
where
public interface ILogger
{
void LogException(Exception ex);
}
public class Logger : ILogger
{
public void LogException(Exception ex)
{
// Log exception
}
}
You can however code this functionality yourself. For example, here is an ASP.NET MVC FilterAttributeFilterProvider, used to inject proprties onto attribute action filters.
public class AttributeFilterProvider : FilterAttributeFilterProvider
{
public AttributeFilterProvider(IKernel kernel)
{
_kernel = kernel;
}
private readonly IKernel _kernel;
protected override IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor);
BuildUpAttributeDependancies(attributes);
return attributes;
}
protected override IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
var attributes = base.GetActionAttributes(controllerContext, actionDescriptor);
BuildUpAttributeDependancies(attributes);
return attributes;
}
private void BuildUpAttributeDependancies(IEnumerable<FilterAttribute> attributes)
{
foreach (var attribute in attributes)
{
var propInfos = attribute.GetType().GetProperties().Where(x => x.GetValue(attribute) == null).AsEnumerable();
foreach (var pi in propInfos)
{
if (_kernel.HasComponent(pi.PropertyType))
{
var service = _kernel.Resolve(pi.PropertyType);
pi.SetValue(attribute, service);
}
}
}
}
}
In the BuildUpAttributeDependancies method, we look for un-initialised (null) properties, and then check to see if the type has been registered with Castle Windsor. If it has, we set the property.
By replacing the default FilterAttributeFilterProvider with our custom one (above) in the global.asax file we can now use Castle Windsors DI features to inject any type onto any Action Filter in our MVC application. To complete this answer fully, here is an example of a global.asax application class with Castle Windsor setup for both Controller (at instantiation time) and ActionFilter (at usage time) dependancy injection:
public class MvcApplication : System.Web.HttpApplication
{
private static IWindsorContainer _container;
private static void BootstrapContainer()
{
_container = new WindsorContainer()
.Install(FromAssembly.This());
var controllerFactory = new ControllerFactory(_container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}
private static void BootstrapFilters()
{
var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider);
FilterProviders.Providers.Remove(oldProvider);
var provider = new AttributeFilterProvider(_container.Kernel);
FilterProviders.Providers.Add(provider);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
BootstrapContainer();
BootstrapFilters();
}
}