我目前正致力于实现延迟定位自托管WCF服务。这些服务在客户端和主机的公共接口中定义合同,这些接口必须从IWCFServiceBase
继承。
WCFHost
托管由IWCFServiceBase
约束的类型参数指定的接口:public class WCFHost<T> where T : WCFServiceBase, IWCFServiceBase
后,客户端可以通过指定接口和服务标识符来订阅此主机:{{1 }}。到目前为止,这个功能完美无瑕。
现在我想尝试对“Lazy-Discover”服务进行排序,并为每个已发现的服务保持可用的通道。此功能由定位器提供,该定位器保存此结构中的所有已发现服务:public class WCFClient<T> : IDisposable where T : IWCFServiceBase
现在假设之前已经使用过服务,因此它已经被发现并保存在字典中,我使用以下代码来检索它:
public Dictionary<string, Dictionary<IWCFServiceBase, WCFClient<IWCFServiceBase>>> Services;
类型 public WCFClient<T> GetMicroService<T>(string servicename, T contract) where T : IWCFServiceBase
{
if (this.Services.ContainsKey(servicename) && this.Services[servicename].ContainsKey(contract))
{
return this.Services[servicename][contract];
}
}
无法隐式转换为Client.WCFClient<WCFCommunication.IWCFServiceBase>
。
显然情况是Client.WCFClient<T>
,除非您考虑类型约束T != IWCFServiceBase
。
那么,为什么C#不这样做,我出错了什么?我觉得在尝试使用泛型时一定有一个很大的错误。
答案 0 :(得分:2)
内部字典只“知道”它有一个WCFCLient<IWCFServiceBase>
作为值。你没有把任何 WCFCLient<IWCFServiceBase>
放在那里。您可能确保只在那里放置正确的值,但编译器无法分辨。你只需要添加一个演员来表明你是肯定的。
我在这里使用TryGetValue
而不是ContainsKey
。假设您可以使用C#7:
public WCFClient<T> GetMicroService<T>(string serviceName, T contract)
where T : IWCFServiceBase
{
if (Services.TryGetValue(serviceName, out var service) &&
service.TryGetValue(contract, out var client))
{
// client will just be WCFClient<IWCFServiceBase>, so we need to cast
return (WCFClient<T>) client;
}
// Throw an exception or whatever...
}
或者out
参数的单独变量声明:
public WCFClient<T> GetMicroService<T>(string serviceName, T contract)
where T : IWCFServiceBase
{
Dictionary<IWCFServiceBase, WCFClient<IWCFServiceBase>> service;
WCFClient<IWCFServiceBase> client;
if (Services.TryGetValue(serviceName, out service) &&
service.TryGetValue(contract, out client))
{
// client will just be WCFClient<IWCFServiceBase>, so we need to cast
return (WCFClient<T>) (object) client;
}
// Throw an exception or whatever...
}