2016-09-18 1 views
2

Je veux développer un système personnalisé pour moi-même.Meilleure pratique pour charger plusieurs services dynamiques et leurs dépendances services

Je veux charger des services personnalisés par configuratin avec les services de dépendance - par exemple:

<Services> 
    <Service name="ServiceA" args="" type="CommonLib.IServiceA" dependencies=""/> 
    <Service name="ServiceB" args="" type="CommonLib.IServiceB" dependencies="ServiceA"/> 
    <Service name="ServiceC" args="" type="CommonLib.IServiceC" dependencies="ServiceA,ServiceB"/> 
    <Service name="ServiceD" args="" type="CommonLib.IServiceD" dependencies="ServiceA,ServiceB,ServiceC"/> 
    <Service name="ServiceE" args="" type="CommonLib.IServiceE" dependencies="ServiceA,ServiceB,ServiceC,ServiceD"/> 
    <Service name="ServiceF" args="" type="CommonLib.IServiceF" dependencies="ServiceA,ServiceB,ServiceC,ServiceD,ServiceE"/> 
</Services> 

Tous ces services sont la mise en œuvre interface personnalisée:

public interface IService 
{ 
    bool Start(); 
    bool Stop(); 
    bool IsReady {get;} 
} 

Ce que les meilleures pratiques pour le chargement des services dynamiques toghether mais dépend de ces dépendances?

En boucle chaque service et de reporter jusqu'à ce que ces dépendances sont chargées et prêtes?

Vous avez un tutoriel pour ça?

+2

Ceci est un [Dépendance graphique] (https://en.wikipedia.org/wiki/Dependency_graph) .. –

+0

il est également tri topologique? bonne idée! –

+0

Oui, les solutions de tri de topologie vous donneront l'ordre de chargement correct. –

Répondre

0

EDIT: La meilleure approche consiste à utiliser des graphiques pour mapper les dépendances pour un service donné. Je viens de mettre un exemple en utilisant le framework Dependency Injection car ils le font déjà. N'hésitez pas à l'utiliser, ou créez le vôtre. L'utilisation d'un outil d'injection de dépendances (Unity, Simple Injector, Autofac, Structure Map, Ninject) permet d'injecter directement les dépendances. Voici un exemple en utilisant l'unité:

var container = new UnityContainer(); 
container.RegisterType<IServiceA, ServiceA>(); 
container.RegisterType<IServiceB, ServiceB>(); 

Lorsque vous demandez par exemple Serviceb, il injectera ServiceA sur elle:

var serviceB = container.Resolve<IServiceB>(); 

En savoir plus sur l'unité: https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx

+0

merci, mais ce n'est pas ma question comment injecter un service, ma question est quelle est la meilleure pratique pour le chargement des services, mais avec la promesse que la dépendance les services sont chargés avant que le service est chargé .. –

+0

juste mettre plus d'informations dans ma réponse. Si vous voulez le faire vous-même, voici un exemple: http://adventuresdotnet.blogspot.co.nz/2009/09/creating-your-own-ioc-container-part-2.html –

0

Après j'obtenir une suggérant de M. Remus Rusanu.

Ma solution est:

Voici l'interface pour le tri topologique:

public interface ITopologicalSort 
    { 
     string Id { get; } 
     IList<ITopologicalSort> Dependencies { get; set; } 
    } 

Le tri topologique:

public static Dictionary<int, IList<T>> TopologicalSort<T>(IEnumerable<T> source, Func<T, IEnumerable<T>> getDependenciesFunc) where T : class, ITopologicalSort 
     { 
      var groups = new Dictionary<string, int>(); 
      var sortedGroups = new Dictionary<int, IList<T>>(); 
      foreach (var item in source) 
      { 
       TopologicalSortInternal(item, getDependenciesFunc, sortedGroups, groups); 
      } 
      return sortedGroups; 
     } 

private static int TopologicalSortInternal<T>(T item, Func<T, IEnumerable<T>> getDependenciesFunc, Dictionary<int, IList<T>> sortedGroups, Dictionary<string, int> groups) where T : class, ITopologicalSort 
     { 
      int level; 
      if (!groups.TryGetValue(item.Id, out level)) 
      { 
       groups[item.Id] = level = INPROCESS; 
       var dependencies = getDependenciesFunc(item); 
       if (dependencies != null && dependencies.Count() > 0) 
       { 
        foreach (var dependency in dependencies) 
        { 
         var depLevel = TopologicalSortInternal(dependency, getDependenciesFunc, sortedGroups, groups); 
         level = Math.Max(level, depLevel); 
        } 
       } 
       groups[item.Id] = ++level; 
       IList<T> values; 
       if (!sortedGroups.TryGetValue(level, out values)) 
       { 
        values = new List<T>(); 
        sortedGroups.Add(level, values); 
       } 
       values.Add(item); 
      } 
      return level; 
     } 

Qu'est-ce que le code est en train de faire? Il est trié par dépendances.

Donc, pour cet exemple:

<Services> 
    <Service name="ServiceA" args="" type="CommonLib.IServiceA" dependencies=""/> 
    <Service name="ServiceB1" args="" type="CommonLib.IServiceB1" dependencies="ServiceA"/> 
    <Service name="ServiceB2" args="" type="CommonLib.IServiceB2" dependencies="ServiceA"/> 
    <Service name="ServiceC1" args="" type="CommonLib.IServiceC1" dependencies="ServiceA,ServiceB1"/> 
    <Service name="ServiceC2" args="" type="CommonLib.IServiceC2" dependencies="ServiceA,ServiceB2"/> 
    <Service name="ServiceD" args="" type="CommonLib.IServiceD" dependencies="ServiceA,ServiceB2,ServiceC2"/> 
    <Service name="ServiceE" args="" type="CommonLib.IServiceE" dependencies="ServiceA,ServiceB2,ServiceC2,ServiceD"/> 
    <Service name="ServiceF" args="" type="CommonLib.IServiceF" dependencies="ServiceA,ServiceB1,ServiceC1,ServiceD,ServiceE"/> 
</Services> 

Level 0: ServiceA 
Level 1: ServiceB1, ServiceB2 
Level 2: ServiceC2, ServiceC2 
Level 3: ServiceD 
Level 4: ServiceE 
Level 5: ServiceF