我正在创建通用服务定位器,但是有问题。 我有一种添加或替换服务的方法。如果当前服务列表中只有1个候选者,则必须替换该服务。
// IA - TestA
// IB - TestB
// IA/IB - TestAB
// <IB> TestAB
public static void AddOrReplaceService<T>(T serviceToAdd) where T: class
{
if (serviceToAdd == null)
throw new ArgumentNullException(nameof(serviceToAdd));
List<T> foundServices = new List<T>();
int index = -1;
for (int i = 0; i < _services.Count; i++)
{
if (!(_services[i] is T)
&& !_services[i].GetType().IsAssignableFrom(typeof(T))
&& !_services[i].GetType().IsInstanceOfType(serviceToAdd)
&& !serviceToAdd.GetType().IsInstanceOfType(_services[i]))
continue;
foundServices.Add((T) _services[i]);
if (index == -1)
index = i;
}
switch (foundServices.Count)
{
case 0:
AddService(serviceToAdd);
break;
case 1:
_services[index] = serviceToAdd;
return;
default:
throw new MultipleServicesAlreadyExistsException("Multiple services found with " + typeof(T).Name
+ foundServices.ToStringCollection(", "));
}
}
要测试我的服务定位器,我有2个接口IA
和IB
以及3个类,TestA : IA
,TestB : IB
和TestAB : IA, IB
问题是,如果TestA
和TestB
都在列表中,而您尝试添加TestAB
则应该给出一个例外,因为TestA
和{{1} }正在实现TestB
的接口。
我尝试添加一堆TestAB
等逻辑。但是,我无法正常工作。
这是单元测试的一部分
AssignableFrom
我们将不胜感激!预先感谢。
答案 0 :(得分:0)
嗯,您的逻辑有缺陷。这是正在发生的事情:
永远不会有一个情况,那就是FoundServices的数量会更多,然后是1。 因此,为了查看抛出异常,您需要从AddOrReplaceService()内部的开关中删除第二条件。而且,除了要添加到集合中的接口之外,您都不应该检查任何接口的实现。
答案 1 :(得分:0)
使用具有接口类型作为键的字典会容易得多,并且由于不需要循环,因此执行起来会更容易。
private static readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();
public static void AddOrReplaceService<T>(T serviceToAdd) where T: class
{
if (serviceToAdd == null)
throw new ArgumentNullException(nameof(serviceToAdd));
_services[typeof(T)] = serviceToAdd;
}
这会自动执行以下操作:
由于您将参数serviceToAdd
键入为T
,因此C#编译器确保服务类的分配与接口T
兼容(无需测试)。另外,无需测试您要替换的服务是否属于正确的类型,因为它是通过相同的方法添加的,只能使用正确的类型的服务来调用。