加载多个动态服务及其依赖服务的最佳实践
本文关键字:服务 最佳 依赖 动态 加载 | 更新日期: 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