OpenRIAServices / OpenRiaServices

The Open RIA Services project continues what was previously known as WCF RIA Services.
https://openriaservices.gitbook.io/openriaservices/
Apache License 2.0
54 stars 47 forks source link

Enhance the code generator to report the root cause(s) of MEF composition exceptions #473

Closed valentinba closed 2 months ago

valentinba commented 6 months ago

Describe the bug

The code generator produces an unhelpful warning:

The following exception occurred creating the MEF composition container: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. The default code generator will be used.

There is no easy way for the user to figure out the root cause of this exception.

To Reproduce

MEFWarning.zip

Open the attached MEFWarning.sln and build it. Notice the one and only warning.

Expected behavior

The code generator should report the root cause(s) of MEF composition exceptions.

Details

Investigation

We use a project structure that resembles the one in the solution attached.

When building this solution, the code generator displays a warning that looks like this:

The following exception occurred creating the MEF composition container: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. The default code generator will be used.

After turning on build debugging one can see this in the build output:

RIA client proxy class generation starting for project 'B.csproj'. Is server project .NETFramework based on TargetFrameworkIdentifier: True Assembly loaded during TaskRun (OpenRiaServices.Tools.CreateOpenRiaClientFilesTask): System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a (location: C:\WINDOWS\Microsoft.Net\assembly\GAC_64\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll, MVID: e7a719b2-5243-47ff-b57e-5f8af3edafb7, AppDomain: [Default]) Assembly 'Microsoft.Win32.Registry, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' could not be loaded and will be ignored. Assembly 'Microsoft.Win32.Registry, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' could not be loaded and will be ignored. Failed to resolve assembly: 'Microsoft.Win32.Registry, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' Assembly 'OpenRiaServices.Server, Version=5.0.0.0, Culture=neutral, PublicKeyToken=2e0b7ccb1ae5b4c8' could not be loaded and will be ignored. Assembly 'OpenRiaServices.Server, Version=5.0.0.0, Culture=neutral, PublicKeyToken=2e0b7ccb1ae5b4c8' could not be loaded and will be ignored. Failed to resolve assembly: 'OpenRiaServices.Server, Version=5.0.0.0, Culture=neutral, PublicKeyToken=2e0b7ccb1ae5b4c8' Assembly 'System.CodeDom, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' could not be loaded and will be ignored. Assembly 'System.CodeDom, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' could not be loaded and will be ignored. Failed to resolve assembly: 'System.CodeDom, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' Assembly 'System.ServiceModel.Syndication, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' could not be loaded and will be ignored. Assembly 'System.ServiceModel.Syndication, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' could not be loaded and will be ignored. Failed to resolve assembly: 'System.ServiceModel.Syndication, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' ...openriaservices.client.codegen\5.4.1\build\OpenRiaServices.Client.CodeGen.targets(341,5): warning : The following exception occurred creating the MEF composition container: ...openriaservices.client.codegen\5.4.1\build\OpenRiaServices.Client.CodeGen.targets(341,5): warning : Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. ...openriaservices.client.codegen\5.4.1\build\OpenRiaServices.Client.CodeGen.targets(341,5): warning : The default code generator will be used.

Unfortunately, the assembly resolution failures shown above the MEF exception are red herrings: they are generated during the shared code service initialization, not during the MEF composition container creation.

Time to spark up the debugger. Following the instructions here https://github.com/OpenRIAServices/OpenRiaServices/wiki/Debugging-Open-Ria-Code-generation-source I was able to determine the actual cause of the warning. It turns out that the exception is a ReflectionTypeLoadException which does offer the actual exceptions in the LoaderExceptions collection.

Could not load file or assembly 'OpenRiaServices.Client, Version=5.0.0.0, Culture=neutral, PublicKeyToken=2e0b7ccb1ae5b4c8' or one of its dependencies. The system cannot find the file specified.

This seems to be caused by project A requiring OpenRiaServices.Client and the dependency resolution jump between the .NET Framework project C and .NET Standard project A not figuring this out.

If I comment out the entire content of the A.A class, properly clean, close, re-open and rebuild the solution, the warning goes away. Alternatively, adding a dependency from C to OpenRiaServices.Client achieves the same goal, but feels weird.

We will try to re-work our code to eliminate the dependency from A to OpenRiaServices.Client but perhaps a small effort in enhancing what is logged will help someone else in the future.

Daniel-Svensson commented 6 months ago

Some issues to fix

  1. add nuget dependency from codegen to client.core (so above error does not happen)
  2. preferable Improve error message: This could maybe be done in logger (in case the code pass exception to logger) and have it check for exception type and add additional output
    • there are 2 separate loggers consolelogger? And cross platform logger which should be updated
    • if/when fixing logging then consider unwrapping AggregateException and TargetInvocationException (I believe there is an existing utility method for this, search for unwrap, exceptionutility or similar]