vs-mef icon indicating copy to clipboard operation
vs-mef copied to clipboard

Fix static member exports to not instantiate declaring type

Open Copilot opened this issue 9 months ago • 7 comments

Problem

When accessing static member exports through MEF, the framework was unnecessarily instantiating the declaring type, even though static members don't require an instance. This caused performance overhead and potential unwanted side effects from constructor execution.

Consider this example:

class Some
{
   [Export]
   public static string Member => "Hi";
}

Before this fix, MEF would instantiate the Some class when obtaining the value of the static Member property, even though instantiation is not necessary for static members.

Root Cause

The issue occurred in two places:

  1. ExportProvider.CreateExport() - Always called GetValueReadyToRetrieveExportingMembers() even for static members, causing instantiation
  2. RuntimeExportProvider.GetExportedValue() - Always created partLifecycle even for static members, which could trigger instantiation

Solution

  • Modified both ExportProvider.CreateExport() and RuntimeExportProvider.GetExportedValue() to check if members are static using MemberRef.IsStatic() before creating part lifecycle trackers
  • For static members, bypass part instantiation entirely and call GetValueFromMember(null, ...) directly
  • Added comprehensive unit tests covering all static member types (fields, properties, methods)

Tests Added

  • StaticFieldExportDoesNotInstantiateClass - Verifies static fields don't cause instantiation
  • StaticPropertyExportDoesNotInstantiateClass - Verifies static properties don't cause instantiation
  • StaticMethodExportDoesNotInstantiateClass - Verifies static methods don't cause instantiation
  • StaticExportInMixedClassDoesNotInstantiateClass - Verifies static exports in mixed classes don't cause instantiation
  • InstanceExportInMixedClassDoesInstantiateClass - Verifies instance exports still work correctly

The fix ensures static member exports perform better and don't have unwanted side effects from unnecessary instantiation, while maintaining full compatibility with existing functionality.

Fixes #593.

[!WARNING]

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 1elvsblobprodwus2177.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • 1mcvsblobprodwus2174.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
  • 1n8vsblobprodwus2184.vsblob.vsassets.io
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • 2wrvsblobprodwus2180.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • 5o1vsblobprodwus2115.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • 5zivsblobprodwus217.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • 78kvsblobprodwus2152.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • 7q7vsblobprodwus2144.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • 7t8vsblobprodwus2168.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
  • 84hvsblobprodwus2148.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • 8wdvsblobprodwus2137.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • 8yfvsblobprodwus2171.vsblob.vsassets.io
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • an0vsblobprodwus2146.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • b15vsblobprodwus2164.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • b5svsblobprodwus2116.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • balvsblobprodwus2129.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • cbvvsblobprodwus2131.vsblob.vsassets.io
    • Triggering command: dotnet build --force (dns block)
  • etjvsblobprodwus2172.vsblob.vsassets.io
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • g3xvsblobprodwus2151.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
  • hd3vsblobprodwus2117.vsblob.vsassets.io
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • i01vsblobprodwus216.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • ia4vsblobprodwus2112.vsblob.vsassets.io
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • izzvsblobprodwus2142.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • jhgvsblobprodwus2167.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
  • jk4vsblobprodwus2186.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js (dns block)
  • jlovsblobprodwus2163.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • jqivsblobprodwus2187.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • mdcvsblobprodwus2159.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • mt2vsblobprodwus2110.vsblob.vsassets.io
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • ndavsblobprodwus219.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
  • nypvsblobprodwus2178.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • p2tvsblobprodwus2189.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • s0ivsblobprodwus2134.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • tn2vsblobprodwus2124.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • v41vsblobprodwus2175.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • vd2vsblobprodwus2150.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • wlnvsblobprodwus2188.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • wztvsblobprodwus2155.vsblob.vsassets.io
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • x1mvsblobprodwus2181.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
  • xktvsblobprodwus2141.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • xofvsblobprodwus2114.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
  • y1mvsblobprodwus2138.vsblob.vsassets.io
    • Triggering command: dotnet build (dns block)
    • Triggering command: dotnet build --force (dns block)
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)
  • zugvsblobprodwus2169.vsblob.vsassets.io
    • Triggering command: dotnet build src/Microsoft.VisualStudio.Composition/Microsoft.VisualStudio.Composition.csproj (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot avatar Jun 11 '25 02:06 Copilot

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

[!WARNING]

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 1elvsblobprodwus2177.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • 2wrvsblobprodwus2180.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • 5o1vsblobprodwus2115.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • 5zivsblobprodwus217.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • 78kvsblobprodwus2152.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • 84hvsblobprodwus2148.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • 8wdvsblobprodwus2137.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • an0vsblobprodwus2146.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • b15vsblobprodwus2164.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • b5svsblobprodwus2116.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • balvsblobprodwus2129.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • cbvvsblobprodwus2131.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • i01vsblobprodwus216.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • izzvsblobprodwus2142.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • jk4vsblobprodwus2186.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • jlovsblobprodwus2163.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • jqivsblobprodwus2187.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • mdcvsblobprodwus2159.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • nypvsblobprodwus2178.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • p2tvsblobprodwus2189.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • s0ivsblobprodwus2134.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • tn2vsblobprodwus2124.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • v41vsblobprodwus2175.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • vd2vsblobprodwus2150.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • wlnvsblobprodwus2188.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • x1mvsblobprodwus2181.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • xktvsblobprodwus2141.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • xofvsblobprodwus2114.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)
  • y1mvsblobprodwus2138.vsblob.vsassets.io
    • Triggering command: dotnet test test/Microsoft.VisualStudio.Composition.Tests/Microsoft.VisualStudio.Composition.Tests.csproj --filter StaticFieldExportDoesNotInstantiateClass --verbosity normal (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot avatar Jun 11 '25 03:06 Copilot

/azp run

AArnott avatar Jun 11 '25 03:06 AArnott

Azure Pipelines successfully started running 1 pipeline(s).

azure-pipelines[bot] avatar Jun 11 '25 03:06 azure-pipelines[bot]

/azp run

AArnott avatar Jun 11 '25 03:06 AArnott

Azure Pipelines successfully started running 1 pipeline(s).

azure-pipelines[bot] avatar Jun 11 '25 03:06 azure-pipelines[bot]

/azp run

AArnott avatar Jun 11 '25 14:06 AArnott

Azure Pipelines successfully started running 1 pipeline(s).

azure-pipelines[bot] avatar Jun 11 '25 14:06 azure-pipelines[bot]