/// <summary> /// Initializes a new instance of the <see cref="ServiceVertex"/> class. /// </summary> /// <param name="service">The service.</param> public ServiceVertex(KernelService service) { { Debug.Assert(service != null, "The service should exist"); } Service = service; }
/// <summary> /// Initializes a new instance of the <see cref="ConnectionMap"/> class. /// </summary> /// <param name="requestedType">Type of the requested service.</param> /// <param name="appliedType">Type of the applied service.</param> public ConnectionMap(Type requestedType, KernelService appliedType) { { Debug.Assert(requestedType != null, "A requested type must be provided."); Debug.Assert(appliedType != null, "An applied type must be provided."); } Requested = requestedType; Applied = appliedType; }
/// <summary> /// Gets the dependency services that are currently available based on the given collection of dependencies. /// </summary> /// <param name="demandedServices">The collection of types which should be matched up with the installed services.</param> /// <returns> /// A collection containing a mapping between the demanded dependency and the service that would /// serve for this dependency. /// </returns> /// <design> /// Note that the current connection strategy only works if there are no demands for duplicates OR /// services with the same interfaces. /// </design> private IEnumerable <KeyValuePair <Type, KernelService> > GetInstalledDependencies(IEnumerable <Type> demandedServices) { // Create a copy of the available service list. Then when we // select a service we'll remove it from this list. var available = new List <KernelService>(from service in m_Services select service.Value); // Dependencies have just gotten a whole lot more complex // We want to be able to match up interfaces & abstract classes too // The problem is that we only want to pass each service only once var result = new List <KeyValuePair <Type, KernelService> >(); foreach (var dependency in demandedServices) { KernelService selected = null; foreach (var storedService in available) { if (dependency.IsAssignableFrom(storedService.GetType())) { selected = storedService; break; } } if (selected != null) { available.Remove(selected); result.Add(new KeyValuePair <Type, KernelService>(dependency, selected)); } if (available.Count == 0) { break; } } return(result); }
/// <summary> /// Provides one of the services on which the current service depends. /// </summary> /// <param name="dependency">The dependency service.</param> public virtual void ConnectTo(KernelService dependency) { // Do nothing here ... }
/// <summary> /// Resets this instance. /// </summary> internal void Reset() { m_Connection = null; }
/// <summary> /// Provides one of the services on which the current service depends. /// </summary> /// <param name="dependency">The dependency service.</param> public override void ConnectTo(KernelService dependency) { m_Connection = dependency; }
/// <summary> /// Gets the services that depend on the specified service type. /// </summary> /// <param name="service">The service type.</param> /// <returns> /// A collection containing a mapping between the demanded dependency and the service that would /// serve for this dependency. /// </returns> private IEnumerable <KeyValuePair <Type, KernelService> > GetDependentServices(KernelService service) { var result = new List <KeyValuePair <Type, KernelService> >(); foreach (var map in m_Services) { var dependencyHolder = map.Value as IHaveServiceDependencies; if (dependencyHolder != null) { foreach (var dependency in dependencyHolder.ServicesToConnectTo()) { if (dependency.IsAssignableFrom(service.GetType())) { result.Add(new KeyValuePair <Type, KernelService>(dependency, map.Value)); break; } } } } return(result); }
/// <summary> /// Installs the specified service. /// </summary> /// <param name="service">The service which should be installed.</param> /// <remarks> /// <para> /// Only services that are 'installed' can be used by the service manager. /// Services that have not been installed are simply unknown to the service /// manager. /// </para> /// <para> /// Note that only one instance for each <c>Type</c> can be provided to /// the service manager. /// </para> /// </remarks> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="service"/> is <see langword="null" />. /// </exception> public void Install(KernelService service) { { Enforce.Argument(() => service); } if ((m_State != StartupState.NotStarted) && (m_State != StartupState.Started)) { throw new KernelNotInInstallReadyStateException(); } if (m_Services.ContainsKey(service.GetType())) { throw new ServiceTypeAlreadyInstalledException(); } var dependencyHolder = service as IHaveServiceDependencies; if (dependencyHolder != null) { if (dependencyHolder.ServicesToConnectTo().Contains(dependencyHolder.GetType())) { throw new ServiceCannotDependOnItselfException(); } if (dependencyHolder.ServicesToConnectTo().Contains(typeof(KernelService))) { throw new ServiceCannotDependOnGenericKernelServiceException(); } var selectedService = GetInstalledDependencies(dependencyHolder.ServicesToConnectTo()); foreach (var map in selectedService) { if (!m_Connections.ContainsKey(service)) { m_Connections.Add(service, new List <ConnectionMap>()); } var connection = m_Connections[service]; connection.Add(new ConnectionMap(map.Key, map.Value)); dependencyHolder.ConnectTo(map.Value); } } var selectedServices = GetDependentServices(service); foreach (var map in selectedServices) { if (!m_Connections.ContainsKey(map.Value)) { m_Connections.Add(map.Value, new List <ConnectionMap>()); } var connection = m_Connections[map.Value]; connection.Add(new ConnectionMap(map.Key, service)); var dependent = map.Value as IHaveServiceDependencies; Debug.Assert(dependent != null, "The service should be able to handle dependencies."); dependent.ConnectTo(service); } m_Services.Add(service.GetType(), service); }
/// <summary> /// Gets the services that depend on the specified service type. /// </summary> /// <param name="service">The service type.</param> /// <returns> /// A collection containing a mapping between the demanded dependency and the service that would /// serve for this dependency. /// </returns> private IEnumerable<KeyValuePair<Type, KernelService>> GetDependentServices(KernelService service) { var result = new List<KeyValuePair<Type, KernelService>>(); foreach (var map in m_Services) { var dependencyHolder = map.Value as IHaveServiceDependencies; if (dependencyHolder != null) { foreach (var dependency in dependencyHolder.ServicesToConnectTo()) { if (dependency.IsAssignableFrom(service.GetType())) { result.Add(new KeyValuePair<Type, KernelService>(dependency, map.Value)); break; } } } } return result; }
/// <summary> /// Installs the specified service. /// </summary> /// <param name="service">The service which should be installed.</param> /// <remarks> /// <para> /// Only services that are 'installed' can be used by the service manager. /// Services that have not been installed are simply unknown to the service /// manager. /// </para> /// <para> /// Note that only one instance for each <c>Type</c> can be provided to /// the service manager. /// </para> /// </remarks> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="service"/> is <see langword="null" />. /// </exception> public void Install(KernelService service) { { Enforce.Argument(() => service); } if ((m_State != StartupState.NotStarted) && (m_State != StartupState.Started)) { throw new KernelNotInInstallReadyStateException(); } if (m_Services.ContainsKey(service.GetType())) { throw new ServiceTypeAlreadyInstalledException(); } var dependencyHolder = service as IHaveServiceDependencies; if (dependencyHolder != null) { if (dependencyHolder.ServicesToConnectTo().Contains(dependencyHolder.GetType())) { throw new ServiceCannotDependOnItselfException(); } if (dependencyHolder.ServicesToConnectTo().Contains(typeof(KernelService))) { throw new ServiceCannotDependOnGenericKernelServiceException(); } var selectedService = GetInstalledDependencies(dependencyHolder.ServicesToConnectTo()); foreach (var map in selectedService) { if (!m_Connections.ContainsKey(service)) { m_Connections.Add(service, new List<ConnectionMap>()); } var connection = m_Connections[service]; connection.Add(new ConnectionMap(map.Key, map.Value)); dependencyHolder.ConnectTo(map.Value); } } var selectedServices = GetDependentServices(service); foreach (var map in selectedServices) { if (!m_Connections.ContainsKey(map.Value)) { m_Connections.Add(map.Value, new List<ConnectionMap>()); } var connection = m_Connections[map.Value]; connection.Add(new ConnectionMap(map.Key, service)); var dependent = map.Value as IHaveServiceDependencies; Debug.Assert(dependent != null, "The service should be able to handle dependencies."); dependent.ConnectTo(service); } m_Services.Add(service.GetType(), service); }