我正在尝试使用 MEF 为 SignalR 创建一个依赖解析器。 到目前为止,我有以下内容:
public class SignalRMefDependencyResolver : DefaultDependencyResolver
{
private readonly CompositionContainer _container;
public SignalRMefDependencyResolver(CompositionContainer container)
{
_container = container;
}
public override object GetService(Type serviceType)
{
var export = _container.GetExports(serviceType, null, null).SingleOrDefault();
return null != export ? export.Value : base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
var exports = _container.GetExports(serviceType, null, null);
var createdObjects = new List<object>();
if (exports.Any())
{
createdObjects.Concat(exports.Select(x => x.Value));
}
createdObjects.Concat(base.GetServices(serviceType));
return createdObjects;
}
}
我认为 GetService 正在工作,但 GetServices 无法找到 IHubDescriptorProvider 和 IMethodDescriptorProvider 的导出 - 无论是在 MEF 中还是在 base 中。
在我的Application_Start中,我有以下第二件事发生 - 第一件事是创建 MEF 容器:
RouteTable.Routes.MapHubs(new SignalRMefDependencyResolver(MefConfig.Container));
我也试过:
GlobalHost.DependencyResolver = new SignalRMefDependencyResolver(MefConfig.Container);
RouteTable.Routes.MapHubs();
结果相同。
我在这里错过了一些明显的东西吗? 我找到的所有样品都是针对其他容器的,看起来要复杂得多。
谢谢
看起来这里的问题是你使用了'Concat()' - 它返回一个新的集合,而不是改变它被调用的集合。
Linq-to-objects运算符(Concat是其中之一)是无副作用的,这意味着当您执行createdObjects.Concat(exports.Select(x => x.Value));
时,连接不会在createdObjects上进行,而是在您决定枚举Concat
的结果时发生。它是一个延迟运算符,因为几乎所有其他返回 IEnumerable<T>
的 Linq 运算符。按执行方式查看标准查询运算符的分类。
现在,要使代码正常工作,请尝试以下操作:
public override IEnumerable<object> GetServices(Type serviceType)
{
var mefExports = _container.GetExports(serviceType, null, null);
//We need this because
var dependencyResolverServices = base.GetServices(serviceType);
if (dependencyResolverServices == null)
{
dependencyResolverServices = Enumerable.Empty<object>();
}
return mefExports.Select(x => x.Value).Concat(dependencyResolverServices);
}
您需要检查 base.GetServices
的返回值,因为 DefaultDependencyResolver 的GetServices
可以返回 null。
然后你所要做的就是枚举你的GetServices
的结果。