Generics and Castle...
Though I knew you could do it, I never have till today... and that's supplying a type for a generic parameter in another type, which is registered in a container... Of course I didn't have to do it that way, but it it kept the configuration a little thinner.
Basically I have some simple WCF services I wanted to host in a container.. here's the service's interface...
[ServiceContract(Namespace="http://localhost/schemas/testrunner/", SessionMode=SessionMode.Required)]
public interface ITestRunner
{
[OperationContract]
Guid StartTestRun(Guid testSuiteId);[OperationContract]
TestRunStatus GetRunStatus(Guid testRunId);
}
To get this to work for my implementation I had to do one thing, which was set the InstanceContextMode to "single" for the service implementations behaviour, otherwise the service host would die when I tried to pass in an instance (it expects a type for any other mode)... I haven't dug very deep into WCF, but it would be nice if they supported a mechanism for supplying a component activator instead...
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class TestRunner : ITestRunner
{
Now, I build a component for hosting my service... it implements IStartable...
public class HostingWrapper: IStartable
where T: class
{
private ServiceHost _host;
private T _service;
private ILogger _log;public HostingWrapper(ILogger log, T service)
{
if (log == null) throw new ArgumentNullException("log");
if (service == null) throw new ArgumentNullException("service");_log = log;
_service = service;
}public void Start()
{
_host = new ServiceHost(_service);
if (_log.IsDebugEnabled) _log.Debug("Opening ServiceHost for service: {0}", _service.GetType());
_host.Open();
if (_log.IsInfoEnabled) _log.Info("Opened ServiceHost for service: {0}", _service.GetType());
}public void Stop()
{
if (_log.IsDebugEnabled) _log.Debug("Closing ServiceHost for service: {0}", _service.GetType());
_host.Close();
((IDisposable)_host).Dispose();
if (_log.IsInfoEnabled) _log.Info("Closed ServiceHost for service: {0}", _service.GetType());
_host = null;
}
}
And then you just need to regsiter it in the container's configuration:
service="BoatsForGoats.Services.Testing.ITestRunner, BoatsForGoats.Services"
type="BoatsForGoats.Services.Testing.TestRunner, BoatsForGoats.Services" />
type="BoatsForGoats.Services.HostingWrapper`1[[BoatsForGoats.Services.Testing.ITestRunner, BoatsForGoats.Services]], BoatsForGoats.Services" />
About the only tricky thing is that I guessed (incorrectly) that I would only need a single set of square brackets around the generic parameter.