Castle Windsor Interceptor for private/protected method - castle-windsor

Is it true that in order for castle windsor's interceptor to intercept a method, that method needs to be declare public?

No it is not true.
The method must be accessible for generated proxy type, which means it must be virtual (or interface method) and it must not be private.
So protected and protected internal methods are good to go. Also internal methods from assembly visible to generated dynamic proxy assembly are OK.

Related

Cannot register the component in castle windsor

I have used the below link for the castle windsor dependency injection.I am not able to register the component.
http://www.codeproject.com/Tips/1052382/ASP-NET-MVC-Dependency-Injection-using-Windsor#_comments
public class ServiceInstaller : IWindsorInstaller
{
public void Install(Castle.Windsor.IWindsorContainer container,
Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
container.Register(
Component.For<Interfaces.TestInterface>()
.ImplementedBy<Services.TestServices>()
.LifestyleTransient());
}
}
ErrorMessage:
An exception of type
'Castle.MicroKernel.ComponentRegistrationException' occurred in
Castle.Windsor.dll but was not handled in user code
Additional information: Component
TestForCastleWindsor.Services.TestServices could not be registered.
There is already a component with that name. Did you want to modify
the existing component instead? If not, make sure you specify a unique
name.
That component is being registered twice. This can happen when IWindsorInstaller implementations or components are picked up by convention. For example, all assemblies in a directory are scanned for implementations of IWindsorInstaller and an old duplicate assembly is present. Or all implementations of another interface also implemented by your component are previously registered.

Managing RavenDb session in Windsor under NServiceBus

I'm using NServiceBus (3.2.2), RavenDB (1.2.2017-Unstable) and Windsor (3.0.0.4001) in an MVC 4 project.
I have a IHandleMessages class that handles 3 different messages, and that needs an IDocumentSession, and therefore defines a property such as:
public IDocumentSession DocumentSession { get; set; }
I've copied the RavenDbUnitOfWork implementation from NServiceBus' website
I've registered IDocumentStore, IDocumentSession and IManageUnitsOfWork in my Windsor container as follow:
container.Register(
Component
.For<IManageUnitsOfWork>()
.ImplementedBy<RavenUnitOfWork>()
.LifestyleTransient()
);
container.Register(
Component
.For<IDocumentStore>()
.UsingFactoryMethod(k => DocumentStoreHolder.DocumentStore)
.LifestyleSingleton(),
Component
.For<IDocumentSession>()
.UsingFactoryMethod(k => k.Resolve<IDocumentStore>().OpenSession())
.LifestyleTransient()
);
NServiceBus is configured to use my container:
Configure.With()
.CastleWindsorBuilder(container);
I'm encountering the problem that the UnitOfWork and the message handler receive different instances of the DocumentSession. This means that objects stored in the session in the message handler are not saved, since SaveChanges() is called on a different DocumentSession.
Removing the Transient lifestyle causes different kind of problems, that result in concurrency/conflicts when updating objects from RavenDb, since (probably) the message handler keeps getting the same instance of the DocumentSession, which holds a cached version of the updated object.
Update:
As suggested, I've tried changing the registration of the IDocumentSession in Windsor, to the Scope lifestyle, like this:
Component
.For<IDocumentSession>()
.UsingFactoryMethod(k => k.Resolve<IDocumentStore>().OpenSession())
.LifestyleScope()
This causes exceptions when the container tries to resolve the MVC Controller, saying that the scope was not found, and asking if I forgot to call BeginScope().
You need to have a scope of Per Message, not transient or singleton.
I am assuming that your mvc controller has a direct dependency on the IDocumentStore. You need to call container.BeginScope() before each request from the web. You can either do this as an action filter attribute http://msdn.microsoft.com/en-us/library/system.web.mvc.actionfilterattribute.aspx or as an AOP aspect on the controller itself http://cangencer.wordpress.com/2011/06/02/asp-net-mvc-3-aspect-oriented-programming-with-castle-interceptors/.
The issue is you need different lifestyles when using nservicebus in an asp.net mvc website when sharing the IDocumentSession in the same container.
For ASP.NET MVC you need a PerWebRequest lifestyle and for NServiceBus you need the Scoped lifestyle.
To do that i've used the hybrid lifestyle code in the castle contrib project:
https://github.com/castleprojectcontrib/Castle.Windsor.Lifestyles/tree/master/Castle.Windsor.Lifestyles
When calling from an ASP.NET context, it uses the WebRequestScopeAccessor. For NServicebus you need the LifetimeScopeAccessor. This is not in the contrib project, but is easy to add:
public class HybridPerWebRequestLifetimeScopeScopeAccessor : HybridPerWebRequestScopeAccessor
{
public HybridPerWebRequestLifetimeScopeScopeAccessor()
: base(new LifetimeScopeAccessor())
{
}
}
And in your registration code you need something like:
container.Register(Component.For<IDocumentSession>().LifestyleScoped<HybridPerWebRequestLifetimeScopeScopeAccessor>().UsingFactoryMethod(() => RavenDbManager.DocumentStore.OpenSession()));
And here's an implementation for Rhino Service Bus i used before switching to nservicebus:
https://gist.github.com/4655544

Register additional component implementations for a service at runtime in Castle Windsor

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.

Castle 3.0 Bound lifestyle - xml configuration

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).

Different ways of accessing configuration parameters from a JAX-WS service

As far as I know I can access the web.xml <context-param>s by making my class implement ServletContextListener and use the ServletContext.getInitParam(String) to read them, but it´s cumbersome as only one instance of the class will receive the contextInitialized(ServletContextEvent sce) call, so I need to make the ServletContext an static member of the class.
What other ways exist of setting conf params at deployment time and what are the recommended ones?
Ok it seems that the best way of actually getting the ServletContext is via the MessageContext as described in How can I access the ServletContext from within a JAX-WS web service?