私は、いくつかのアセンブリ(コア、ドメイン、バックエンドMVC、フロントエンドMVCなど)に分割されたより大きなC#MVC 4プロジェクトに取り組んでいます。 MEFが提供するプラグインアーキテクチャを使用して、ほとんどの依存関係をロードして解決します。今私はMVCコントローラをロードするためにそれを使いたいと思っていました。典型的なシナリオは数十のサンプルにあります。MVCコントローラでMEFを使用しようとするとCompositionContractMismatchExceptionが発生する
しかし、私はこの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
カスタム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;
}
そして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;
}
のEv erythingはこのように設定されています DependencyResolver.SetResolver(new CustomDependencyResolver(container)); ControllerBuilder.Current.SetControllerFactory(新しいSomeCustomControllerFactory(container));
サイドノート:MEF2 RegistrationBuilderと、3つのAssemblyCatalogと1つのDirectoryCatalogを持つAggregateCatalogが使用されています。
メインプロジェクトソリューションから抽出し、新しいmvc 4インターネットプロジェクトソリューションを作成してそこに統合すると、すべてが完璧に機能します。 (1つのアセンブリで2番目のシンプルなコアライブラリでテスト済み)
私は既にCompositionOptions.DisableSilentRejectionをオンにしました。そして、このリソースがMEF関連のエラーをデバッグするのを見つけましたhttps://blogs.msdn.com/b/dsplaisted/archive/2010/07/13/how-to-debug-and-diagnose-mef-failures.aspx?Redirected=true 私はHomeController(Emptyコンストラクタ、インポートなしなど)のすべてを削除しました。 MEF容器は適切な輸出品で満たされています。すべてうまい。
デバッグと研究の一日の後、私はMEFについて多くのことを学んだが、同じ問題を抱えている。うまくいけば、誰かが私にヒントが間違って欲しいと思うかもしれない。新しいMVCプロジェクトにすべてを移動する原因は、非常に非常に時間がかかる。これは、同じアセンブリが異なるcontexesにまたはから2回ロードされたときに、時にはスローされるSystem.InvalidCastExceptionに似:-(
ありがとう!
あなたの答えをありがとう。あなたは基本的にSystem.InvalidCastExceptionです。別の日のデバッグとあなたのリンクを読んだ後、私はそれを理解しました。いくつかの理由で(一部の.dllの深いところまで依存関係があると仮定しています)、私はbin /ディレクトリ全体に対して別のDirectoryCatalogを追加しなければなりませんでした。 – Andreas
これが発生する可能性がある別のケースは、テストを含むディレクトリの下にテストランナーが作成する "TestResults"ディレクトリです。 MEFはこれらのテストディレクトリを再帰し、同じDLLのコピーを探します。 –
私はこの問題を抱えていましたが、別のソリューションから自分のコードを実行しているときだけでした。デバッガがアセンブリをロードしていたことを示します。 – sdgfsdh