And*_*eas 9 c# mef asp.net-mvc-4
我正在开发一个更大的C#MVC 4项目,该项目分为几个程序集(Core,Domain,Backend MVC,Frontend MVC等).我使用MEF提供的插件架构来加载和解决大多数依赖项.现在我也想用它来加载MVC控制器.在几十个样本中发现了典型的场景.
但我一直得到这个YSOD:
例外说:
[CompositionContractMismatchException: Cannot cast the underlying exported value of type "XY.HomeController (ContractName="XY.HomeController")" to type "XY.HomeController".]
System.ComponentModel.Composition.ExportServices.CastExportedValue(ICompositionElement element, Object exportedValue) +505573
System.ComponentModel.Composition.<>c__DisplayClass10`2.<CreateSemiStronglyTypedLazy>b__c() +62
System.Lazy`1.CreateValue() +14439352
System.Lazy`1.LazyInitValue() +91
XY.DependencyManagement.SomeCustomControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) in (Path)\Core\DependencyManagement\SomeCustomControllerFactory.cs:32
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +89
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +305
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +87
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +12550291
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
Run Code Online (Sandbox Code Playgroud)
自定义ControllerFactory:
public class SomeCustomControllerFactory : DefaultControllerFactory {
private readonly CompositionContainer _compositionContainer;
public SomeCustomControllerFactory (CompositionContainer compositionContainer) {
_compositionContainer = compositionContainer;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
var export = _compositionContainer.GetExports(controllerType, null, null).SingleOrDefault();
IController result;
if (export != null) {
result = export.Value as IController;
} else {
result = base.GetControllerInstance(requestContext, controllerType);
_compositionContainer.ComposeParts(result);
}
return result;
}
protected override Type GetControllerType(RequestContext requestContext, string controllerName) {
Type controllerType = base.GetControllerType(requestContext, controllerName);
// used to find objects in the container which assemblies are in a sub directory and not discovered by MVC
// TODO: only create parts that are used
if (controllerType == null && this._compositionContainer != null &&
this._compositionContainer != null) {
var controllerTypes =
this._compositionContainer.GetExports<Controller, IDictionary<string, object>>()
.Where(
e =>
e.Value.GetType().Name.ToLowerInvariant() ==
controllerName.ToLowerInvariant() + ControllerNameByConvention)
.Select(e => e.Value.GetType()).ToList();
switch (controllerTypes.Count) {
case 0:
controllerType = null;
break;
case 1:
controllerType = controllerTypes.First();
break;
case 2:
throw CreateAmbiguousControllerException(requestContext.RouteData.Route, controllerName,
controllerTypes);
}
}
return controllerType;
}
Run Code Online (Sandbox Code Playgroud)
和CustomDependencyResolver:
public class CustomDependencyResolver : IDependencyResolver {
private readonly CompositionContainer _container;
public CustomDependencyResolver(CompositionContainer container) {
_container = container;
}
public IDependencyScope BeginScope() {
return (IDependencyScope)this;
}
public object GetService(Type serviceType) {
var export = _container.GetExports(serviceType, null, null).SingleOrDefault();
return null != export ? export.Value : null;
}
public IEnumerable<object> GetServices(Type serviceType) {
var exports = _container.GetExports(serviceType, null, null);
var createdObjects = new List<object>();
if (exports.Any()) {
foreach (var export in exports) {
createdObjects.Add(export.Value);
}
}
return createdObjects;
}
Run Code Online (Sandbox Code Playgroud)
一切都是这样配置DependencyResolver.SetResolver(new CustomDependencyResolver(container)); ControllerBuilder.Current.SetControllerFactory(new SomeCustomControllerFactory(container));
附注:使用MEF2 RegistrationBuilder和带有三个AssemblyCatalog和一个DirectoryCatalog的AggregateCatalog.
如果我从主项目解决方案中提取它并创建一个新的mvc 4互联网项目解决方案并将其集成在那里,整个过程就完美无缺.(使用一个程序集测试它,使用第二个简单的核心库.)
我已经打开了CompositionOptions.DisableSilentRejection.并找到此资源来调试与MEF相关的错误https://blogs.msdn.com/b/dsplaisted/archive/2010/07/13/how-to-debug-and-diagnose-mef-failures.aspx?Redirected=true 我删除了HomeController中的所有内容(空构造函数,没有导入等).MEF容器装有合适的出口.一切都很好.
经过一整天的调试和研究,我学到了很多关于MEF的知识,但仍然遇到了同样的问题.希望有人能在这里给我一个提示错误.将所有内容移动到新的MVC项目会非常非常耗时:-(
谢谢!
Pan*_*nis 13
这看起来类似于System.InvalidCastException,当在不同的上下文或不同的位置加载两次相同的程序集时,有时会抛出这种情况.MEF中的所有程序集加载都由AssemblyCatalog类使用Assembly.Load(AssemblyName)方法处理,该方法将在Load上下文中加载具有给定名称的程序集.但是,在某些情况下,它会将它加载到LoadFrom上下文中,这有时会导致转换异常,例如您提到的异常:
无法将类型为"XY.HomeController(ContractName ="XY.HomeController")"的基础导出值强制转换为"XY.HomeController"类型.
我要做的是查看包含的程序集XY.HomeController是否部署在多个位置.如果它是一个强大的命名程序集,请不要忘记查看GAC.
Telerik的论坛中提到了类似的问题.
如果您想了解有关此主题的更多详细信息,请查看"运行时如何查找程序集" "程序集加载的最佳实践"以及Suzanne Cooks MSDN博客中与Load相关的条目.
| 归档时间: |
|
| 查看次数: |
4039 次 |
| 最近记录: |