Skip to content

Commit

Permalink
Extract interface from ServiceManager, convert some methods to extens…
Browse files Browse the repository at this point in the history
…ion methods, implement caching for GetService<T>() method, and make some methods virtual
  • Loading branch information
cdhowie committed Mar 18, 2013
1 parent e9816e3 commit a076f5a
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 22 deletions.
5 changes: 5 additions & 0 deletions Cdh.Toolkit.Services/Cdh.Toolkit.Services.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,17 @@
<Compile Include="ServiceManager.cs" />
<Compile Include="ThreadedService.cs" />
<Compile Include="LightService.cs" />
<Compile Include="IServiceManager.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Cdh.Toolkit.Collections\Cdh.Toolkit.Collections.csproj">
<Project>{A2E1EDA8-78B8-4717-8B75-0D1A2AC47F15}</Project>
<Name>Cdh.Toolkit.Collections</Name>
</ProjectReference>
<ProjectReference Include="..\Cdh.Toolkit.Extensions\Cdh.Toolkit.Extensions.csproj">
<Project>{1F804DDB-FFB0-4D57-B5DD-03389FAC1836}</Project>
<Name>Cdh.Toolkit.Extensions</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
42 changes: 42 additions & 0 deletions Cdh.Toolkit.Services/IServiceManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using Cdh.Toolkit.Extensions;
using System.Collections.Generic;

namespace Cdh.Toolkit.Services
{
public interface IServiceManager
{
void RegisterService(IService service);
void UnregisterService(IService service);

IEnumerable<T> GetServices<T>() where T : IService;
T GetService<T>() where T : IService;
}

public static class ServiceManagerExtensions
{
public static T RequireService<T>(this IServiceManager serviceManager) where T : IService
{
Check.ArgumentIsNotNull(serviceManager, "serviceManager");

var service = serviceManager.GetService<T>();

if (service == null) {
throw new InvalidOperationException(string.Format(
"There is not exactly one service of type {0} registered.", typeof(T).FullName));
}

return service;
}

public static void RegisterAndStartService(this IServiceManager serviceManager, IService service)
{
Check.ArgumentIsNotNull(serviceManager, "serviceManager");
Check.ArgumentIsNotNull(service, "service");

serviceManager.RegisterService(service);
service.Start();
}
}
}

66 changes: 44 additions & 22 deletions Cdh.Toolkit.Services/ServiceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,58 +30,80 @@
using System.Text;

using Cdh.Toolkit.Collections;
using System.Threading;
using Cdh.Toolkit.Extensions.ReaderWriterLockSlim;

namespace Cdh.Toolkit.Services
{
public class ServiceManager
public class ServiceManager : IServiceManager
{
private SynchronizedCollection<IService> services =
new SynchronizedCollection<IService>(new HashSet<IService>(), EnumerateBehavior.Lock);
protected ReaderWriterLockSlim Lock { get; private set; }

protected ICollection<IService> ServiceCollection { get; private set; }

public ICollection<IService> Services { get; private set; }

private Dictionary<Type, IService> serviceCache = new Dictionary<Type, IService>();

public ServiceManager()
{
Services = new ReadOnlyCollection<IService>(services);
Lock = new ReaderWriterLockSlim();

ServiceCollection = new HashSet<IService>();

Services = new ReadOnlyCollection<IService>(new SynchronizedCollection<IService>(ServiceCollection, EnumerateBehavior.Lock, Lock));
}

public void RegisterService(IService service)
public virtual void RegisterService(IService service)
{
if (service == null)
throw new ArgumentNullException("service");

services.Add(service);
}
using (Lock.Write()) {
ServiceCollection.Add(service);

public void RegisterAndStartService(IService service)
{
RegisterService(service);
service.Start();
PurgeCache();
}
}

public void UnregisterService(IService service)
public virtual void UnregisterService(IService service)
{
if (service == null)
throw new ArgumentNullException("service");

services.Remove(service);
using (Lock.Write()) {
ServiceCollection.Remove(service);

PurgeCache();
}
}

public T GetService<T>() where T : IService
protected void PurgeCache()
{
return services.OfType<T>().SingleOrDefault();
serviceCache.Clear();
}

public T RequireService<T>() where T : IService
public virtual IEnumerable<T> GetServices<T>() where T : IService
{
var service = GetService<T>();

if (service == null) {
throw new InvalidOperationException(string.Format(
"Required service type {0} not registered.", typeof(T).FullName));
using (Lock.Read()) {
return ServiceCollection.OfType<T>().ToList();
}
}

public virtual T GetService<T>() where T : IService
{
using (Lock.Read()) {
IService cachedService;
if (serviceCache.TryGetValue(typeof(T), out cachedService)) {
return (T)cachedService;
}

var service = GetServices<T>().SingleOrDefault();

return service;
serviceCache[typeof(T)] = service;

return service;
}
}
}
}

0 comments on commit a076f5a

Please sign in to comment.