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.
Related
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();
}
I want to auto register all interfaces which name ends with "Service" and also doesn't have concrete implementations to be resolved to a generated type/proxy (which off course differs per interface).
So when I want to resolve IContractService I want it to return a proxied object. I got this idea from this article where they implemented it in some way with Castle Windsor.
What would be the structuremap approach for achieving this. I tried all kind of things with custom conventions and all but I can't get my head around it.
I fixed this by using Castle's Dynamic Proxy and a StructureMap convention. BTW. I also renamed some of the classes mentioned in the article.
public class InfraRegistry : Registry
{
public InfraRegistry()
{
For<IClientProviderFactory>().Use<WcfClientProviderProviderFactory>();
Scan(scan =>
{
scan.AssemblyContainingType<MidleWareServiceConvention>();
scan.Convention<MidleWareServiceConvention>();
});
}
}
public class MidleWareServiceConvention : IRegistrationConvention
{
private readonly ProxyGenerator _proxyGen = new ProxyGenerator();
public void Process(Type type, Registry registry)
{
if (type.IsInterface && type.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase))
{
registry.For(type)
.HybridHttpOrThreadLocalScoped()
.Use(
context =>
_proxyGen.CreateInterfaceProxyWithoutTarget(type,
new WcfInterceptor(
context.GetInstance<IClientProviderFactory>())));
}
}
}
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.
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();
I have a model roughly like this:
public interface IUnitOfWork { }
public class UnitOfWork : IUnitOfWork { }
public interface IService { }
public class Service : IService
{
public IUnitOfWork UnitOfWork { get; set; }
}
public class ViewModel
{
public IService Service { get; set; }
}
And a configuration that could be like this:
container.Register(Component.For<IService>().ImplementedBy<Service>()
.LifeStyle.Transient
Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>()
.LifeStyle.Transient,
Component.For<ViewModel>().LifeStyle.Transient);
I need to resolve, at different points, two instances of ViewModel (I'm using a typed factory for this, but let's leave that aside for simplicity and assume I'm using the raw container)
The catch is that I need to resolve two instances of ViewModel at different points (from another ViewModel that knows about both), and they need to share the same IUnitOfWork.
So, something like this:
var vm1 = container.Resolve<ViewModel>();
//...later
var vm2 = container.Resolve<ViewModel>();
Now, it's very easy to share the Service. I'd just have to do something like:
var vm2 = container.Resolve<ViewModel>(new { vm1.Service });
But of course the actual model is more complicated (different ViewModels, with more Services each), so that's not an option.
I can pass the UnitOfWork to Resolve, but it doesn't get used by default (which makes sense). Is there any way to use that parameter (probably by registering a delegate somewhere) when resolving the second ViewModel?
I'd like to be able to do the following:
var vm2 = container.Resolve<ViewModel>(new { UnitOfWork });
And get a ViewModel whose Service has that specific UnitOfWork.
If you need to share a component and you cannot set as singleton(rich client) or perwebrequest, you need to use Contextual lifestyle.
check this thread see my last comment to downoload contrib w/ Contextual Lifestyle
For you case I assume those 2 ViewModel will be used by 1 View... so View + UoW require Contextual Lifestyle
check also this one too see comments at the end
The solution was to use ContextualLifestyle coupled with a custom factory that kept a reference to the ContainerContext, in order to use the same one when resolving another ViewModel.