Castle Windsor Interceptor on Caliburn View Model - castle-windsor

I would like create own aspects with Castle Windsor Interceptor and apply on View Model classes.
As I said I use Caliburn MVVM framework and on DI I use Caste Windsor. Everything works good.
For example I created simple loggging interceptors, here is:
public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Write("Log: Method Called: " + invocation.Method.Name);
invocation.Proceed();
}
}
This is simple View Model class - it is "tab item" :
public class TabViewModel : Screen,
ITabViewModel
{
}
When I configure IoC with Fluent API I would like apply this interceptor on View Model class.
container.Register(Component
.For<LoggingInterceptor>()
.LifeStyle
.Singleton
.Named("LogAspect"));
container.Register(Component
.For<ITabViewModel>()
.ImplementedBy<TabViewModel>()
.LifeStyle
.Transient
.Named("TabViewModel")
.Interceptors<LoggingInterceptor>());
When I tried pick view model from IoC:
var tabItem = IoC.Get<ITabViewModel>();
ActivateItem(tabItem);
I got this message:
A default view was not found for Castle.Proxies.ITabViewModelProxy.
Views searched for include: Castle.Proxies.IITabViewModelProxy
Castle.Proxies.ITabViewModelProxys.IDefault
Castle.Proxies.ITabViewModelProxys.Default
Also I tried this way for interceptor applicaion.
[Interceptor(typeof(LoggingInterceptor))]
public class TabViewModel : Screen,
ITabViewModel
{
}
Ok, I know that Caliburn framework match View and View Model by naming convention.
When I try pick implementation of ITabViewModel I get ITabViewModelProxy and for ITabViewModelProxy I didn’t register any View.
Target of proxy is TabViewModel but I think problem is with naming mismatch.
I dont want rename ViewModel because I would like configure proxies from XML files.
So what is correct way?
Thank you for help

What about this?
void Hack()
{
var existing = ViewLocator.TransformName;
ViewLocator.TransformName = (s, o) =>
existing(s.EndsWith("Proxy")
? s.Substring(0, s.Length - "Proxy".Length)
: s, o);
}

The easiest way (and probably robust) is to suggest to Caliburn's ViewLocator to use not the type of view model's proxy but the type of the view model that's being proxied:
public static void AddViewLocatorRuleForProxiedViewModels()
{
var originalViewTypeLocator = ViewLocator.LocateTypeForModelType;
ViewLocator.LocateTypeForModelType = (modelType, displayLocation, context) =>
{
var viewModelType = modelType;
var viewModelTypeName = viewModelType.FullName;
if (viewModelTypeName.StartsWith("Castle.Proxies") && viewModelTypeName.EndsWith("Proxy"))
viewModelType = viewModelType.BaseType;
return originalViewTypeLocator(viewModelType, displayLocation, context);
};
}

Related

Replacement for #helper in ASP.NET Core

So far, i don't think ViewComponent solves that neither does TagHelper. Is there any replacement to this? Something that takes parameters and returns a HtmlString?
I don't see anything harmful with:
#helper foo(string something) {
<div>Say #something</div>
}
var emailbody = classfilenameinAppCodefolder.foo("hello"); //store result in a variable for further processes
For now i believe its a temporary delete before RC. https://github.com/aspnet/Razor/issues/281 and https://github.com/aspnet/Mvc/issues/1130 Well! it better be. I hope someone is working on it. Without #helper, building large HtmlString or 'template' would be a serious pain.
Note: Partial View doesn't seem to do the trick. I think it only renders views not return view to variable.
Secondly, what happened to the App_Code folder?
According to the following Github issue, it looks like #helper is coming back and will be included in asp .net core 3.0.0 preview 4.
https://github.com/aspnet/AspNetCore/issues/5110
UPDATE
Starting in asp .net core 3, you can now define a local function within a Razor code block.
#{
void RenderName(string name)
{
<p>Name: <strong>#name</strong></p>
}
RenderName("Mahatma Gandhi");
RenderName("Martin Luther King, Jr.");
}
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-3.1#razor-code-blocks
Alternatively you can use the #functions directive like this:
#{
RenderName("Mahatma Gandhi");
RenderName("Martin Luther King, Jr.");
}
#functions {
private void RenderName(string name)
{
<p>Name: <strong>#name</strong></p>
}
}
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-3.1#functions
#{
Func<String, IHtmlContent> foo = #<div>Say #item</div>;
}
I'd like to expand on #Alexaku's answer and show how I've implemented a helper like function. It's only useful on one specific page but it allows you to execute a piece of razor code multiple times with input parameters. The syntax is not great but I've found it very useful in the absence of razor's #helper function. First declare some kind of Dto that will contain the input parameters into the function.
#functions {
private class Dto
{
public string Data { get;set; }
}
}
Then declare the razor function. Note that the displayItem value can be multi-line and also note that you access the Dto variable using the #item.
#{
Func<Dto, IHtmlContent> displayItem = #<span>#item.Data</span>;
}
Then when you want to use the razor template you can call it like the following from anywhere in the page.
<div>
#displayItem(new Dto {Data = "testingData1" });
</div>
<div>
#displayItem(new Dto {Data = "testingData2" });
</div>
For .NET Core 3, you can use local functions:
#{
void RenderName(string name)
{
<p>Name: <strong>#name</strong></p>
}
RenderName("Mahatma Gandhi");
RenderName("Martin Luther King, Jr.");
}
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-3.1#razor-code-blocks
As #scott pointed out in his answer, local functions are finally available as of .NET Core 3. In prior versions one can resort to templated Razor delegates.
But none of the answers addresses the question "what happened to the App_Code folder?" The aforementioned features are local solutions, that is, helper functions defined in these ways cannot be shared between multiple views. But global helper functions could often be more convenient than the solutions MS provide out-of-the-box for view-related code re-use. (Tag helpers, partial views, view components all have their cons.) This was thoroughly discussed in this and this GitHub issue. According to these discourses, unfortunately, there's not much understanding from MS's side, so not much hope is left that this feature will be added any time soon, if ever.
However, after digging into the framework sources, I think, I could come up with a viable solution to the problem.
The core idea is that we can utilize the Razor view engine to look up an arbitrary view for us: e.g. a partial view which defines some local functions we want to use globally. Once we manage to get hold of a reference to this view, nothing prevents us from calling its public methods.
The GlobalRazorHelpersFactory class below encapsulates this idea:
public interface IGlobalRazorHelpersFactory
{
dynamic Create(string helpersViewPath, ViewContext viewContext);
THelpers Create<THelpers>(ViewContext viewContext) where THelpers : class;
}
public class GlobalRazorHelpersOptions
{
public Dictionary<Type, string> HelpersTypeViewPathMappings { get; } = new Dictionary<Type, string>();
}
public sealed class GlobalRazorHelpersFactory : IGlobalRazorHelpersFactory
{
private readonly ICompositeViewEngine _viewEngine;
private readonly IRazorPageActivator _razorPageActivator;
private readonly ConcurrentDictionary<Type, string> _helpersTypeViewPathMappings;
public GlobalRazorHelpersFactory(ICompositeViewEngine viewEngine, IRazorPageActivator razorPageActivator, IOptions<GlobalRazorHelpersOptions>? options)
{
_viewEngine = viewEngine ?? throw new ArgumentNullException(nameof(viewEngine));
_razorPageActivator = razorPageActivator ?? throw new ArgumentNullException(nameof(razorPageActivator));
var optionsValue = options?.Value;
_helpersTypeViewPathMappings = new ConcurrentDictionary<Type, string>(optionsValue?.HelpersTypeViewPathMappings ?? Enumerable.Empty<KeyValuePair<Type, string>>());
}
public IRazorPage CreateRazorPage(string helpersViewPath, ViewContext viewContext)
{
var viewEngineResult = _viewEngine.GetView(viewContext.ExecutingFilePath, helpersViewPath, isMainPage: false);
var originalLocations = viewEngineResult.SearchedLocations;
if (!viewEngineResult.Success)
viewEngineResult = _viewEngine.FindView(viewContext, helpersViewPath, isMainPage: false);
if (!viewEngineResult.Success)
{
var locations = string.Empty;
if (originalLocations.Any())
locations = Environment.NewLine + string.Join(Environment.NewLine, originalLocations);
if (viewEngineResult.SearchedLocations.Any())
locations += Environment.NewLine + string.Join(Environment.NewLine, viewEngineResult.SearchedLocations);
throw new InvalidOperationException($"The Razor helpers view '{helpersViewPath}' was not found. The following locations were searched:{locations}");
}
var razorPage = ((RazorView)viewEngineResult.View).RazorPage;
razorPage.ViewContext = viewContext;
// we need to save and restore the original view data dictionary as it is changed by IRazorPageActivator.Activate
// https://github.com/dotnet/aspnetcore/blob/v3.1.6/src/Mvc/Mvc.Razor/src/RazorPagePropertyActivator.cs#L59
var originalViewData = viewContext.ViewData;
try { _razorPageActivator.Activate(razorPage, viewContext); }
finally { viewContext.ViewData = originalViewData; }
return razorPage;
}
public dynamic Create(string helpersViewPath, ViewContext viewContext) => CreateRazorPage(helpersViewPath, viewContext);
public THelpers Create<THelpers>(ViewContext viewContext) where THelpers : class
{
var helpersViewPath = _helpersTypeViewPathMappings.GetOrAdd(typeof(THelpers), type => "_" + (type.Name.StartsWith("I", StringComparison.Ordinal) ? type.Name.Substring(1) : type.Name));
return (THelpers)CreateRazorPage(helpersViewPath, viewContext);
}
}
After introducing the singleton IGlobalRazorHelpersFactory service to DI, we could inject it in views and call the Create method to acquire an instance of the view which contains our helper functions.
By using the #implements directive in the helper view, we can even get type-safe access:
#inherits Microsoft.AspNetCore.Mvc.Razor.RazorPage
#implements IMyGlobalHelpers
#functions {
public void MyAwesomeGlobalFunction(string someParam)
{
<div>#someParam</div>
}
}
(One can define the interface type to view path mappings explicitly by configuring the GlobalRazorHelpersOptions in the ordinary way - by services.Configure<GlobalRazorHelpersOptions>(o => ...) - but usually we can simply rely on the naming convention of the implementation: in the case of the IMyGlobalHelpers interface, it will look for a view named _MyGlobalHelpers.cshtml at the regular locations. Best to put it in /Views/Shared.)
Nice so far but we can do even better! It'd be much more convenient if we could inject the helper instance directly in the consumer view. We can easily achieve this using the ideas behind IOptions<T>/HtmlLocalizer<T>/ViewLocalizer:
public interface IGlobalRazorHelpers<out THelpers> : IViewContextAware
where THelpers : class
{
THelpers Instance { get; }
}
public sealed class GlobalRazorHelpers<THelpers> : IGlobalRazorHelpers<THelpers>
where THelpers : class
{
private readonly IGlobalRazorHelpersFactory _razorHelpersFactory;
public GlobalRazorHelpers(IGlobalRazorHelpersFactory razorHelpersFactory)
{
_razorHelpersFactory = razorHelpersFactory ?? throw new ArgumentNullException(nameof(razorHelpersFactory));
}
private THelpers? _instance;
public THelpers Instance => _instance ?? throw new InvalidOperationException("The service was not contextualized.");
public void Contextualize(ViewContext viewContext) => _instance = _razorHelpersFactory.Create<THelpers>(viewContext);
}
Now we have to register our services in Startup.ConfigureServices:
services.AddSingleton<IGlobalRazorHelpersFactory, GlobalRazorHelpersFactory>();
services.AddTransient(typeof(IGlobalRazorHelpers<>), typeof(GlobalRazorHelpers<>));
Finally, we're ready for consuming our global Razor functions in our views:
#inject IGlobalRazorHelpers<IMyGlobalHelpers> MyGlobalHelpers;
#{ MyGlobalHelpers.Instance.MyAwesomeGlobalFunction("Here we go!"); }
This is a bit more complicated than the original App_Code + static methods feature but I think this is the closest we can get. According to my tests, the solution also works nicely with runtime compilation enabled. I haven't had the time so far to do benchmarks but, in theory, it should generally be faster than using partial views as the shared view is looked up only once per consumer view and after that it's just plain method calls. I'm not sure about tag helpers though. It'd be interesting to do some benchmarks comparing them. But I leave that up to the adopter.
(Tested on .NET Core 3.1.)
Update
You can find a working demo of this concept in my ASP.NET boilerplate project:
Infrastructure (relevant files are only those whose name contains GlobalRazorHelpers)
Registration
Helper interface sample
Helper implementation sample
Usage sample
The #helper directive was removed since it was incomplete and its current design did not fit in the new 'ASP.NET 5 way'. One of the reasons is that helpers should be declared in the App_Code folder while ASP.NET 5 has no concept of special folders. Therefore the team decided to temporarily remove the feature.
There are plans to bring it back in the future though. See this and this.
You can easily replace that "feature" with a ViewComponent (and a TagHelper if you want). ASP.NET Core is much more friendly to web designers, and the ViewComponents allow you to write HTML without any (weird to most) razor code.
For example:
Create a SayComponent : ViewComponent class:
public class SayComponent : ViewComponent
{
public void Render(string message)
{
return View(message);
}
}
Create a View file under Views/Shared/Say/Default.cshtml with just
#model string
<div>Message: #Model.</div>
And call it:
#await Component.RenderAsync("Say", "some message")
For a better experience, add this to your _ViewImports.cshtml file:
#addTagHelper *, YourSolutionName
And then you can use it as a tag helper:
<vc:say message="some message"></vc:say>
How about using partials to recreate reusable tags?
MyProject/Views/Shared/_foo.cshtml
#model string
<div>#Model</div>
MyProject/Views/Courses/Index.cshtml
#{
Layout = "_Layout";
}
<div>
<partial name="_foo" model="foo" />
<partial name="_foo" model="bar" />
<partial name="_foo" model="baz" />
</div>

Any alternative to injecting Castle Windsor typed factories?

Most of my components are registered using the code-based (fluent) approach, but there is one particular component that I need to resolve differently at runtime. This is the interface and a couple of concrete implementations:-
public interface ICommsService ...
public class SerialCommsService : ICommsService ...
public class TcpCommsService : ICommsService ...
Some of our users will need the serial service while others will need the TCP service. My current solution (which works btw) is to use a typed factory and a custom component selector - the latter reads an app.config setting to determine which implementation the typed factory will resolve and return.
First the typed factory (nothing special about this):-
public interface ICommsServiceFactory
{
ICommsService Create();
void Release(ICommsService component);
}
Next, the custom component selector, which reads the fully-qualified type name from app.config (e.g. "MyApp.SomeNamespace.TcpCommsService"):-
public class CommsFactoryComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
return ConfigurationManager.AppSettings["commsServiceType"];
}
}
Then the registration stuff:-
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ITypedFactoryComponentSelector>()
.ImplementedBy<CommsFactoryComponentSelector>());
container.Register(Component.For<ICommsFactory>()
.AsFactory(o => o.SelectedWith<CommsFactoryComponentSelector>()));
container.Register(Component.For<ICommsService>()
.ImplementedBy<SerialCommsService>().LifeStyle.Singleton);
container.Register(Component.For<ICommsService>()
.ImplementedBy<TcpCommsService>().LifeStyle.Singleton);
Finally, an example class with a dependency on ICommsService:-
public class Test
{
public Test(ICommsFactory commsFactory)
{
var commsService = commsFactory.Create();
...
}
}
As already mentioned, the above solution does work, but I don't like having to inject the factory. It would be more intuitive if I could just inject an ICommsService, and let something somewhere figure out which implementation to resolve and inject - similar to what I'm doing now but earlier in Windsor's "resolving pipeline". Is something like that possible?
You can use UsingFactoryMethod here:
container.Register(Component.For<ICommsService>().UsingFactoryMethod(kernel => kernel.Resolve<ICommsServiceFactory>().Create()));
You can inject ICommsService to any class now. ICommsServiceFactory can be a simple interface now:
interface ICommsServiceFactory
{
ICommsService Create();
}

Castle Windsor - how to resolve by name?

My application uses the "SignalR" client/server comms framework. If you aren't familiar with it, the server-side app typically contains one or more "hub" classes (similar to asmx web services), each providing methods that can be called by a client. During startup, the client needs to first create a connection, then create a "proxy" for each hub that it will need to talk to, e.g.:-
var hubConnection = new HubConnection("http://...");
var fooHubProxy = hubConnection.CreateHubProxy("FooHub");
var barHubProxy = hubConnection.CreateHubProxy("BarHub");
...etc...
The string parameter passed to CreateHubProxy() is the name of the server-side hub class. The method return type is IHubProxy.
It feels like I should be able to utilise Windsor here, but I'm struggling to find a solution. My first thought was to instantiate the hub proxies and register these instances with Windsor (by name), e.g.
var fooHubProxy = hubConnection.CreateHubProxy("FooHub");
container.Register(Component.For<IHubProxy>().Instance(fooHubProxy).LifestyleSingleton().Named("FooHub"));
...etc...
The problem is that when a class needs a hub proxy, the only way to resolve it by name is to use service locator pattern, which isn't recommended. What other Windsor features (e.g. typed factories, etc.) might be useful here?
Edit
I've just found Windsor's .UsingFactoryMethod, and am wondering if this would work, to simplify hub registration:
container.Register(Component.For<IHubProxy>()
.UsingFactoryMethod((kernel, context) => hubConnection.CreateHubProxy("FooHub"))
.LifestyleSingleton()
.Named("FooHub"));
I guess I still have the problem of how to resolve by name though.
Two years later, but I have a more elegant solution for other people that stummble accross this problem too.
It is possible to use TypedFactory facility and adapt it to you needs like here.
first create the factory interface (only! no need for the actual implementation, castle will take care of that):
public interface IHubProxyFactory
{
IHubProxy GetProxy(string proxyName);
}
Now we need a class that extend the default typed facotory and retreives the component's name from the input (proxyName):
class NamedTypeFactory : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
string componentName = null;
if (arguments!= null && arguments.Length > 0)
{
componentName = arguments[0] as string;
}
if (string.IsNullOrEmpty(componentName))
componentName = base.GetComponentName(method, arguments);
return componentName;
}
}
And then register the factory with castle and specify that your NamedTypeFactory will be used:
Component.For<IHubProxyFactory>().AsFactory(new NamedTypeFactory())
Now every class can get the factory interface in its constructor:
public class SomeClass
{
private IHubProxy _fooHub;
private IHubProxy _barHub;
public SomeClass(IHubProxyFactory hubProxyFactory)
{
_fooHub = hubProxyFactory.GetProxy("FooHub");
_barHub = hubProxyFactory.GetProxy("BarHub");
}
}
Okay, I think I've found a possible solution, partly using the approach detailed here which shows how it is possible to register Func<>s with Windsor.
First, I register a delegate (Func<>) that uses the container to resolve by name:-
Container.Register(Component.For<Func<string, IHubProxy>>()
.Instance(name => Container.Resolve<IHubProxy>(name))
.LifestyleSingleton());
Think of this as an IHubProxy "factory".
Next, I register my hub proxies as detailed in my original question:-
container.Register(Component.For<IHubProxy>()
.UsingFactoryMethod((kernel, context) => hubConnection.CreateHubProxy("FooHub"))
.LifestyleSingleton()
.Named("FooHub"));
container.Register(Component.For<IHubProxy>()
.UsingFactoryMethod((kernel, context) => hubConnection.CreateHubProxy("BarHub"))
.LifestyleSingleton()
.Named("BarHub"));
Here is an example of a class that needs instances of the hub proxies:-
public class SomeClass
{
private IHubProxy _fooHub;
private IHubProxy _barHub;
public SomeClass(Func<string, IHubProxy> hubProxyFactory)
{
_fooHub = hubProxyFactory("FooHub");
_barHub = hubProxyFactory("BarHub");
}
}
Untried so far, but it looks promising. It's a clever solution but injecting the Func<> feels a little hacky, so I would still be keen to hear of other possible solutions to my problem.
I just used a similar method to yours. I use a typed Factory. Advantage is I have type safety for my hubs. Registering the hubs is the same. The rest differs a bit but is technical the same.
IServiceFactory {
IHubProxy GetFooHub();
IHubProxy GetBarHub();
}
And Registration:
Container.AddFacility<TypedFactoryFacility>();
Container.Register(Component.For<IServiceFactory>().AsFactory());
Usage:
public class SomeClass
{
private IHubProxy _fooHub;
private IHubProxy _barHub;
public SomeClass(IServiceFactry hubProxyFactory)
{
_fooHub = hubProxyFactory.GetFooHub();
_barHub = hubProxyFactory.GetBarHub();
}
}
Btw. Factory.Get"Name"() resolves by name.

Intercepting the concrete implementation (as opposed to service) using Castle Windsor

I'm experimenting with interception in Castle Windsor and notice that interceptors seem to be created as decorators of my service interface.
In other words, if I have an interface "ISomethingDoer" and a concrete "ConcreteSomethingDoer", the proxy implements ISomethingDoer but does not inherit from ConcreteSomethingDoer.
This is fine, and no doubt by design, but what I'm wondering is whether I can intercept protected virtual methods in my concrete classes that wouldn't be known by the public interface. I am doing this in order to add logging support, but I might want to log some of the specific internal details of a class.
In my slightly unimaginative test case I have this:
public interface ISomethingDoer
{
void DoSomething(int Count);
}
[Loggable]
public class ConcreteSomethingDoer : ISomethingDoer
{
public void DoSomething(int Count)
{
for (var A = 0; A < Count; A++)
{
DoThisThing(A);
}
}
[Loggable]
protected virtual void DoThisThing(int A)
{
("Doing a thing with " + A.ToString()).Dump();
}
}
So what I want to do is log calls to "DoThisThing" even though it's not part of the interface.
I've managed to get this working in Autofac. (I've created a Linqpad script here: http://share.linqpad.net/frn5a2.linq) but am struggling with Castle Windsor (see http://share.linqpad.net/wn7877.linq)
In both cases my interceptor is the same and looks like this:
public class Logger : IInterceptor
{
public void Intercept(IInvocation Invocation)
{
String.Format("Calling method {0} on type {1} with parameters {2}",
Invocation.Method.Name,
Invocation.InvocationTarget.GetType().Name,
String.Join(", ", Invocation.Arguments.Select(a => (a ?? "*null*").ToString()).ToArray())).Dump();
Invocation.Proceed();
"Done".Dump();
}
}
What I really want to do is say "any classes with a [Loggable] attribute, should use the logging interceptor". In the Autofac example I've specifically attached a logger to the registration, whereas with Castle I'm using an IModelInterceptorsSelector which looks like this:
public class LoggerInterceptorSelector : IModelInterceptorsSelector
{
public bool HasInterceptors(ComponentModel Model)
{
return Model.Implementation.IsDefined(typeof(LoggableAttribute), true);
}
public InterceptorReference[] SelectInterceptors(ComponentModel Model, InterceptorReference[] Interceptors)
{
return new[]
{
InterceptorReference.ForType<Logger>()
};
}
}
Finally, the code to execute all this is:
var Container = new WindsorContainer();
Container.Register(
Component.For<Logger>().LifeStyle.Transient
);
Container.Kernel.ProxyFactory.AddInterceptorSelector(new LoggerInterceptorSelector());
Container.Register(
Component.For<ISomethingDoer>()
.ImplementedBy<ConcreteSomethingDoer>()
.LifeStyle.Transient
);
var Doer = Container.Resolve<ISomethingDoer>();
Doer.DoSomething(5);
When run I would expect to see "Calling method DoThisThing with parameters x" for each time the method is called. Instead I only get the call to DoSomething logged.
I can see why Castle Windsor is doing this, but I'm wondering if there is a way to tweak the behaviour?
(As a side-note I don't want to use Windsor's own interceptor attributes as I don't want to introduce dependencies to Castle outside of my composition root.)
I have tried resolving the ConcreteSomethingDoer specifically and this works, but not if I'm resolving the ISomethingDoer.
Apologies for the long post, and also apologies because I am pretty new to Castle Windsor!
I you could register like:
Container.Register(
Component.For<ISomethingDoer, ConcreteSomethingDoer>()
.ImplementedBy<ConcreteSomethingDoer>()
.LifeStyle.Transient
);
This should create a class proxy by deriving from ConcreteSomethingDoer. However this won't work with dynamic interceptors. However you probably can work around that by creating a facility which registers the interceptor when needed.

How do I register multiple services with a specific interface in Castle Windsor

I have the following registration:
container.Register(AllTypes.FromAssemblyContaining<ITabViewModel>().BasedOn<ITabViewModel>());
Two classes:
public class StructureDecorationViewModel : NotificationObject, ITabViewModel
{
...
}
public abstract class NotificationObject : INotifyPropertyChanged
{
...
}
And two resolvers:
serviceProvider.ResolveAll<System.ComponentModel.INotifyPropertyChanged>()
serviceProvider.ResolveAll<ITabViewModel>()
Both of these Resolvers gives the StructureDecorationViewModel, how can I filter the registration so that I only register the ITabViewModel and not the INotifyPropertyChange?
To register against just one interface you would normally use FirstInterface:
AllTypes
.FromAssemblyContaining<ITabViewModel>()
.BasedOn<ITabViewModel>()
.WithService
.FirstInterface();
However in this case you would end up with your service registered against INotifyPropertyChanged which is not what you want as it picks the first interface from the base class (Have a look at the ServiceDescriptor class to see what other registrations are available).
What you need is the Select method that allows you to define the type or types you want to register the service against:
AllTypes
.FromAssemblyContaining<ITabViewModel>()
.BasedOn<ITabViewModel>()
.WithService
.Select(typeof(ITabViewModel));
However if you want to keep things more generic someone has written an extension method that looks at the service being registered and picks out the first interface on the derived class (http://www.hightech.ir/SeeSharp/windsor-registration-service-interface):
public static BasedOnDescriptor FirstInterfaceOnClass(this ServiceDescriptor serviceDescriptor)
{
return serviceDescriptor.Select((t, bt) =>
{
var baseInterfaces = t.BaseType.GetInterfaces();
var interfaces = t.GetInterfaces().Except(baseInterfaces);
return interfaces.Count() != 0 ? new[] {interfaces.First()} : null;
});
}
Which allows you to do this:
AllTypes
.FromAssemblyContaining<ITabViewModel>()
.BasedOn<ITabViewModel>()
.WithService
.FirstInterfaceOnClass();