Fix static member exports to not instantiate declaring type
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:
-
ExportProvider.CreateExport()- Always calledGetValueReadyToRetrieveExportingMembers()even for static members, causing instantiation -
RuntimeExportProvider.GetExportedValue()- Always createdpartLifecycleeven for static members, which could trigger instantiation
Solution
- Modified both
ExportProvider.CreateExport()andRuntimeExportProvider.GetExportedValue()to check if members are static usingMemberRef.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:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to my firewall allow list
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:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to my firewall allow list
/azp run
Azure Pipelines successfully started running 1 pipeline(s).
/azp run
Azure Pipelines successfully started running 1 pipeline(s).
/azp run
Azure Pipelines successfully started running 1 pipeline(s).