gpt4 book ai didi

c# - 尝试将 MEF 与 MVC Controller 一起使用时出现 CompositionContractMismatchException

转载 作者:太空狗 更新时间:2023-10-29 17:43:30 25 4
gpt4 key购买 nike

我正在开发一个更大的 C# MVC 4 项目,该项目分为几个程序集(核心、域、后端 MVC、前端 MVC 等)。我使用 MEF 提供的插件架构来加载和解决大多数依赖项。现在我还想让它用来加载 MVC Controller 。几十个样本中发现的典型场景。

但我一直收到这个 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

自定义 Controller 工厂:

 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;
}

还有一个 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;
}

一切都是这样配置的DependencyResolver.SetResolver(新的 CustomDependencyResolver(容器));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 项目将非常非常耗时:-(

谢谢!

最佳答案

这看起来类似于 System.InvalidCastException当同一个程序集在不同上下文中或从不同位置加载两次时,有时会抛出此错误。 MEF 中的所有程序集加载都由 AssemblyCatalog 处理使用 Assembly.Load(AssemblyName) 的类方法,该方法将在 Load 上下文中加载具有给定名称的程序集。然而,在certain conditions下,它会将其加载到 LoadFrom 上下文中,这有时会导致强制转换异常,例如您提到的异常:

Cannot cast the underlying exported value of type "XY.HomeController(ContractName="XY.HomeController")" to type "XY.HomeController".]

我要做的是查看包含 XY.HomeController 的程序集是否部署在多个位置。如果它是强命名程序集,请不要忘记查看 GAC。

Telerik's forum中提到了类似的问题.

如果您想了解有关此主题的更多详细信息,请查看 "How the Runtime Locates Assemblies" "Best Practices for Assembly Loading"以及 Suzanne Cooks MSDN blog 中与负载相关的条目.

关于c# - 尝试将 MEF 与 MVC Controller 一起使用时出现 CompositionContractMismatchException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14316978/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com