VsixCommunity / Community.VisualStudio.Toolkit.DependencyInjection

Adds Dependency Injection tooling for the Community.VisualStudio.Toolkit
Other
14 stars 7 forks source link

Cannot instantiate implementation type 'Community.VisualStudio.Toolkit.DependencyInjection.Core.BaseDICommand' for service type 'Community.VisualStudio.Toolkit.DependencyInjection.Core.BaseDICommand' #16

Closed icnocop closed 1 month ago

icnocop commented 1 month ago

Hi.

Thank you for Community.VisualStudio.Toolkit.DependencyInjection.

I created a VSIX extension for Visual Studio 2022 with a command which uses DI and it works in a Visual Studio Experimental Instance when debugging the extension.

However, when I install it from the marketplace and try to use it, the following warning dialog appears:

---------------------------
Microsoft Visual Studio
---------------------------
The 'MyExtensionPackage' package did not load correctly.

The problem may have been caused by a configuration change or by the installation of another extension. You can get more information by examining the file 'C:\Users\name\AppData\Roaming\Microsoft\VisualStudio\17.0_8b505217\ActivityLog.xml'.

Restarting Visual Studio could help resolve this issue.

Continue to show this error message?
---------------------------
Yes   No   
---------------------------

The following entry appears in ActivityLog.xml:

  <entry>
    <record>2708</record>
    <time>2024/07/24 05:16:58.940</time>
    <type>Error</type>
    <source>VisualStudio</source>
    <description>SetSite failed for package [MyExtensionPackage]Source: &apos;Microsoft.Extensions.DependencyInjection&apos; Description: Cannot instantiate implementation type &apos;Community.VisualStudio.Toolkit.DependencyInjection.Core.BaseDICommand&apos; for service type &apos;Community.VisualStudio.Toolkit.DependencyInjection.Core.BaseDICommand&apos;.&#x000D;&#x000A;System.ArgumentException: Cannot instantiate implementation type &apos;Community.VisualStudio.Toolkit.DependencyInjection.Core.BaseDICommand&apos; for service type &apos;Community.VisualStudio.Toolkit.DependencyInjection.Core.BaseDICommand&apos;.&#x000D;&#x000A;   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.Populate()&#x000D;&#x000A;   at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)&#x000D;&#x000A;   at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)&#x000D;&#x000A;   at Community.VisualStudio.Toolkit.DependencyInjection.Microsoft.MicrosoftDIToolkitPackage`1.BuildServiceProvider(IServiceCollection serviceCollection)&#x000D;&#x000A;   at Community.VisualStudio.Toolkit.DependencyInjection.DIToolkitPackage`1.&lt;InitializeAsync&gt;d__0.MoveNext()&#x000D;&#x000A;--- End of stack trace from previous location where exception was thrown ---&#x000D;&#x000A;   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()&#x000D;&#x000A;   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)&#x000D;&#x000A;   at MyExtension.MyExtensionPackage.&lt;InitializeAsync&gt;d__1.MoveNext() in D:\a\MyExtension\MyExtension\src\MyExtension\MyExtensionPackage.cs:line 59&#x000D;&#x000A;--- End of stack trace from previous location where exception was thrown ---&#x000D;&#x000A;   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()&#x000D;&#x000A;   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)&#x000D;&#x000A;   at Microsoft.VisualStudio.Shell.AsyncPackage.&lt;&gt;c__DisplayClass21_0.&lt;&lt;Microsoft-VisualStudio-Shell-Interop-IAsyncLoadablePackageInitialize-Initialize&gt;b__1&gt;d.MoveNext()&#x000D;&#x000A;--- End of stack trace from previous location where exception was thrown ---&#x000D;&#x000A;   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()&#x000D;&#x000A;   at Microsoft.VisualStudio.Services.VsTask.RethrowException(AggregateException e)&#x000D;&#x000A;   at Microsoft.VisualStudio.Services.VsTask.InternalGetResult(Boolean ignoreUIThreadCheck)</description>
    <guid>{4B43DB1A-E109-4FD4-83A9-4E41F8BB44B3}</guid>
    <hr>0x80070057 - E_INVALIDARG</hr>
    <errorinfo></errorinfo>
  </entry>
</activity>

I registered my commands using services.RegisterCommands(ServiceLifetime.Singleton);.

Steps to reproduce:

  1. Install the extension from the marketplace https://marketplace.visualstudio.com/items?itemName=RamiAbughazaleh.MigratePackagesConfigToPackageReferencesExtension
  2. Clone the repo: https://github.com/icnocop/MigratePackagesConfigToPackageReferencesExtension
  3. Open DemoApp.sln
  4. Right-click on DemoApp\packages.config and select Migrate packages.config to PackagesReferences...

When I open MigratePackagesConfigToPackageReferences.sln and debug the extension, the error does not occur.

Any advice?

Thank you.

icnocop commented 1 month ago

I was able to resolve the issue by calling

services.RegisterCommands(ServiceLifetime.Singleton, Assembly.GetExecutingAssembly());

Instead of this:

services.RegisterCommands(ServiceLifetime.Singleton);
icnocop commented 1 month ago

I think the cause is described in this blog post: https://ticklishtechs.net/2010/03/04/be-careful-when-using-getcallingassembly-and-always-use-the-release-build-for-testing/index.html

If the method that calls the GetCallingAssembly method is expanded inline by the compiler (that is, if the compiler inserts the function body into the emitted Microsoft intermediate language (MSIL), rather than emitting a function call), then the assembly returned by the GetCallingAssembly method is the assembly containing the inline code. This might be different from the assembly that contains the original method. To ensure that a method that calls the GetCallingAssembly method is not inlined by the compiler, you can apply the MethodImplAttribute attribute with MethodImplOptions.NoInlining.