加载多个动态服务及其依赖服务的最佳实践

本文关键字:服务 最佳 依赖 动态 加载 | 更新日期: 2023-09-27 18:07:23

我想为自己开发一个自定义系统。

我想通过配置依赖服务来加载自定义服务——例如:

<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>

所有这些服务都实现了自定义接口:

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

将动态服务加载在一起但依赖于这些依赖项的最佳实践是什么?

循环每个服务并延迟直到那些依赖项加载并准备好?

有相关教程吗?

加载多个动态服务及其依赖服务的最佳实践

编辑:最好的方法是使用图来映射给定服务的依赖关系。我只是举了一个使用依赖注入框架的例子,因为他们已经这样做了。请随意使用,或者创建您自己的。

使用任何依赖注入工具(Unity, Simple Injector, Autofac, Structure Map, Ninject)都会直接注入依赖。下面是一个使用Unity的例子:

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

当你请求ServiceB实例时,它会在它上面注入ServiceA:

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

关于Unity的更多信息:https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx

我得到Remus Rusanu先生的建议后。

我的解决方案是:

下面是拓扑排序的接口:

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

拓扑排序:

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;
        }

代码在做什么?他按依赖项排序。

对于这个例子:

<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