Giter Site home page Giter Site logo

microsoft / vs-mef Goto Github PK

View Code? Open in Web Editor NEW
403.0 33.0 86.0 9.57 MB

Managed Extensibility Framework (MEF) implementation used by Visual Studio

License: MIT License

Batchfile 0.04% PowerShell 4.67% C# 95.25% Dockerfile 0.05%
mef visual-studio extensibility extensibility-engine

vs-mef's Introduction

vs-mef

Build Status codecov Join the chat at https://gitter.im/vs-mef/Lobby

This repo contains the Visual Studio team's implementation of .NET's managed extensibility framework. It is broken up into several NuGet packages, as listed below.

Microsoft.VisualStudio.Composition

NuGet package

Lightning fast MEF engine, supporting System.ComponentModel.Composition and System.Composition.

Features

  • A new, faster host for your existing MEF parts
  • Reuse the MEF attributes you're already using
  • ExportFactory<T> support to create sub-containers with scoped lifetime (i.e. sharing boundaries)

Documentation

Learn more about this package.

Microsoft.VisualStudio.Composition.Analyzers

NuGet package

Analyzers for MEF consumers to help identify common errors in MEF parts.

Learn more about this package.

Microsoft.VisualStudio.Composition.AppHost

NuGet package

Adds a VS MEF system with a pre-computed, cached MEF graph.

Learn more about this package.

Microsoft.VisualStudio.Composition.VSMefx

NuGet package

A diagnostic tool to understand catalogs, compositions and diagnose issues in them.

Learn more about this package.

vs-mef's People

Contributors

aarnott avatar adrianvmsft avatar alexeyler avatar ankitvarmait avatar csigs avatar csiusers avatar davkean avatar dependabot[bot] avatar jasonmalinowski avatar javierdlg avatar jmarolf avatar joerobich avatar kirillosenkov avatar lukka avatar matteo-prosperi avatar milopezc avatar mohit-chakraborty avatar pjchristmas avatar ref12public avatar sarda-devesh avatar stephentoub avatar stevebush avatar sylviale191 avatar therzok avatar tinaschrepfer avatar toddgrun avatar trevors20 avatar v-zbsail avatar wade0016 avatar zoeyr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vs-mef's Issues

Avoid loading assemblies from cached catalogs when composing

When one of the assemblies that contribute to the MEF catalog are changed, we have to rescan that assembly, then we have to recompose the graph. Although scanning an assembly is relatively quick, composing the graph can take a long time, and loads many assemblies in the process even though they weren't changed from their cached catalog versions.

There are at least two reasons why composing loads assemblies from the catalog, and I think we can solve them.

TypeRefs are considered equal if they are built by an assembly with the same path but a different assembly name

Repro:

AssemblyName a1 = CreateAssemblyName("AssemblyA", new Version(1, 0), CultureInfo.CurrentCulture, @"C:\some\path\AssemblyA.dll", publicKey: publicKey);
AssemblyName a2 = CreateAssemblyName("AssemblyA", new Version(2, 0), CultureInfo.CurrentCulture, @"C:\some\path\AssemblyA.dll");
Assert.NotEqual(TypeRef.Get(a1, ...), TypeRef.Get(a2, ...));

The reason is that ByValueEquality+AssemblyNameComparer returns true whenever the code bases are equal.

The scenario occurs when we compare the MEF cache and the newly created MEF graph to see if they are equivalent (if they are equivalent, we don't serialize the new graph to save time). Since the MEF cache was created with a different version of the assembly, VS MEF should not consider the code base "fast check" (the AssemblyName in the cache was created by a different process).

This is the root cause of feedback item 447376 in DevDiv.

PartDiscovery.CreatePartsAsync() deadlocks when called synchronously from UI thread

I've been a fan of MEF for quite a while and very excited to see some development on it.

My WPF app is .NET Framework 4.6.1. When using 15.8.55-alpha (I needed the InheritedExportAttribute), the example 'Hosting MEF in an extensible application' just never returns when calling from the App.xaml.cs OnStartup method.

var catalog = ComposableCatalog.Create(Resolver.DefaultInstance)
.AddParts(discovery.CreatePartsAsync(Assembly.GetExecutingAssembly()).Result)
.WithCompositionService(); // Makes an ICompositionService export available to MEF parts to import

Can we get a full example of how MEF should be composted in a WPF application?

[QUESTION] Example of documentation claim

Can you please document, inline, in Why VS-MEF?, what you mean by:

VS MEF utilizes a fully precomputed and validated composition graph for maximum throughput when constructing MEF exports. This also produces a complete list of compositional diagnostics that describe MEF parts that were rejected from the graph with root causes and cascading effects identified.

Seems cool, but hard to wrap my head around the claim. Even pointing to what test cases assert this functionality would be super helpful.

How to use MEF v3?

In ExportProviderTests I see this comment:

// MEFv3 is more lazy at activating parts than MEFv1 and MEFv2.

That sounds like a very interesting feature. We are currently using MEFv1 and plan to switch to v2, but v3 sounds even more promising. How do you migrate to v3?

I suppose we need to change this part:

var discovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(resolver));

Unit-tests that run in another AppDomain should use serializable asserts

When all unit-tests are passing, everything is OK. However imagine a test breaks (actually true on Mono), instead of getting a readable assert you get:

Type 'Xunit.Sdk.FalseException' in assembly 'xunit.assert, Version=2.0.0.2929, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c' is not marked as serializable.

This is because xUnit's assert exceptions aren't serializable (and it's by design unfortunately), so you don't get a good message about the failure.

To simulate this, insert an Assert.False(true); at this line for example:
https://github.com/Microsoft/vs-mef/blob/master/src/tests/Microsoft.VisualStudio.Composition.Tests/AssembliesLazyLoadedTests.cs#L296

Then run the ComposableAssembliesLazyLoadedByLazyImport test.

Maybe it's worth creating a custom serializable AssertException and have an Assert() helper method in AppDomain tests that throws that and preserves a good message when serialized across appdomains?

Unstable test: LazyOfNonSharedPartConstructsOnlyOneInstanceAcrossThreadsV1

In this Travis-CI test run we see this test failure:

[xUnit.net 00:00:32.8217164]     V1 [FAIL]
[xUnit.net 00:00:32.8228982]       System.AggregateException : One or more errors occurred. (Assert.Equal() Failure
[xUnit.net 00:00:32.8229538]       Expected: 1
[xUnit.net 00:00:32.8229830]       Actual:   0)
[xUnit.net 00:00:32.8230114]       ---- Assert.Equal() Failure
[xUnit.net 00:00:32.8230378]       Expected: 1
[xUnit.net 00:00:32.8230661]       Actual:   0
[xUnit.net 00:00:32.8241112]       Stack Trace:
[xUnit.net 00:00:32.8254893]            at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
[xUnit.net 00:00:32.8255617]            at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
[xUnit.net 00:00:32.8256053]            at System.Threading.Tasks.Task.Wait()
[xUnit.net 00:00:32.8256716]         /home/travis/build/Microsoft/vs-mef/src/tests/Microsoft.VisualStudio.Composition.Tests/ThreadSafetyTests.cs(188,0): at Microsoft.VisualStudio.Composition.Tests.ThreadSafetyTests.LazyOfNonSharedPartConstructsOnlyOneInstanceAcrossThreads(IContainer container, Boolean permitMultipleInstancesOfNonSharedPart)
[xUnit.net 00:00:32.8257431]         /home/travis/build/Microsoft/vs-mef/src/tests/Microsoft.VisualStudio.Composition.Tests/ThreadSafetyTests.cs(133,0): at Microsoft.VisualStudio.Composition.Tests.ThreadSafetyTests.LazyOfNonSharedPartConstructsOnlyOneInstanceAcrossThreadsV1(IContainer container)
[xUnit.net 00:00:32.8257887]         ----- Inner Stack Trace -----
[xUnit.net 00:00:32.8258389]         /home/travis/build/Microsoft/vs-mef/src/tests/Microsoft.VisualStudio.Composition.Tests/ThreadSafetyTests.cs(182,0): at Microsoft.VisualStudio.Composition.Tests.ThreadSafetyTests.<>c__DisplayClass8_0.<<LazyOfNonSharedPartConstructsOnlyOneInstanceAcrossThreads>b__2>d.MoveNext()
Failed   V1
Error Message:
 System.AggregateException : One or more errors occurred. (Assert.Equal() Failure
Expected: 1
Actual:   0)
---- Assert.Equal() Failure
Expected: 1
Actual:   0
Stack Trace:
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at Microsoft.VisualStudio.Composition.Tests.ThreadSafetyTests.LazyOfNonSharedPartConstructsOnlyOneInstanceAcrossThreads(IContainer container, Boolean permitMultipleInstancesOfNonSharedPart) in /home/travis/build/Microsoft/vs-mef/src/tests/Microsoft.VisualStudio.Composition.Tests/ThreadSafetyTests.cs:line 188
   at Microsoft.VisualStudio.Composition.Tests.ThreadSafetyTests.LazyOfNonSharedPartConstructsOnlyOneInstanceAcrossThreadsV1(IContainer container) in /home/travis/build/Microsoft/vs-mef/src/tests/Microsoft.VisualStudio.Composition.Tests/ThreadSafetyTests.cs:line 133
----- Inner Stack Trace -----
   at Microsoft.VisualStudio.Composition.Tests.ThreadSafetyTests.<>c__DisplayClass8_0.<<LazyOfNonSharedPartConstructsOnlyOneInstanceAcrossThreads>b__2>d.MoveNext() in /home/travis/build/Microsoft/vs-mef/src/tests/Microsoft.VisualStudio.Composition.Tests/ThreadSafetyTests.cs:line 182

I believe this is because both LazyOfNonSharedPartConstructsOnlyOneInstanceAcrossThreadsV1 and LazyOfNonSharedPartConstructsOnlyOneInstanceAcrossThreadsV2 reset the same static field to 0 and increment that field during the test, so if the xunit test runner runs these two methods in parallel, we have cross-contamination of the tests. We should make these tests thread-safe.

MEF error log should include assembly information when multiple exports with same fully qualified type name are encountered

I was doing some work and ended up with a MEF problem where the error file said:

Microsoft.VisualStudio.CodeSense.Editor.Roslyn.CodeElementTaggerProvider.ctor(visualStudioIntegrationService): expected exactly 1 export of Microsoft.VisualStudio.Alm.Roslyn.Client.IVisualStudioIntegrationService but found 2.
    Microsoft.VisualStudio.Alm.Roslyn.Client.VisualStudioIntegrationService
    Microsoft.VisualStudio.Alm.Roslyn.Client.VisualStudioIntegrationService
   part definition Microsoft.VisualStudio.CodeSense.Editor.Roslyn.CodeElementTaggerProvider
 
Microsoft.VisualStudio.CodeSense.Editor.Roslyn.CodeElementTaggerProvider.ctor(visualStudioIntegrationService): is not assignable from exported MEF value Microsoft.VisualStudio.Alm.Roslyn.Client.VisualStudioIntegrationService.
   part definition Microsoft.VisualStudio.CodeSense.Editor.Roslyn.CodeElementTaggerProvider

Which makes it hard to figure out where the two types are coming from. Using MEFCollect.exe I was able to see the below, which made it clearer. It would be great to include the assembly identity (and location) in cases like this.

995: Microsoft.VisualStudio.Alm.Roslyn.Client.VisualStudioIntegrationService (in Microsoft.VisualStudio.Alm.Shared.CodeAnalysisClient)
                Metadata Token: 33554439
                Sharing Boundary: none
                IsShared: True
                IsInstantiable: True
                Importing Constructor:
                                Metadata Token: 100663319
                                Arguments: 2
                                                Microsoft.VisualStudio.Alm.Roslyn.Client.VisualStudioIntegrationService (in Microsoft.VisualStudio.Alm.Shared.CodeAnalysisClient)
                                                                Declaring Type's Metadata Token: 33554439
                                                                Cardinality: ExactlyOne
                                                                IsExportFactory: False
                                                                IsLazy: False
                                                                IsNonSharedInstanceRequired: False
                                                                SatisfyingExports: 1
                                                                                #1: Contract Name: Microsoft.VisualStudio.Shell.SVsServiceProvider
                                                                                                Exported Type: Microsoft.VisualStudio.Shell.SVsServiceProvider
                                                                                                Exported Type's Assembly: Microsoft.VisualStudio.Shell.Framework, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
                                                                                                Exported Type's Metadata Token: 33554500
                                                                                                Metadata: 1
                                                                                                                ExportTypeIdentity: Microsoft.VisualStudio.Shell.SVsServiceProvider
                                                Microsoft.VisualStudio.Alm.Roslyn.Client.VisualStudioIntegrationService (in Microsoft.VisualStudio.Alm.Shared.CodeAnalysisClient)
                                                                Declaring Type's Metadata Token: 33554439
                                                                Cardinality: ExactlyOne
                                                                IsExportFactory: False
                                                                IsLazy: False
                                                                IsNonSharedInstanceRequired: False
                                                                SatisfyingExports: 1
                                                                                #1: Contract Name: Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.VisualStudioWorkspaceImpl
                                                                                                Exported Type: Microsoft.VisualStudio.LanguageServices.RoslynVisualStudioWorkspace
                                                                                                Exported Type's Assembly: Microsoft.VisualStudio.LanguageServices.Implementation, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
                                                                                                Exported Type's Metadata Token: 33554435
                                                                                                Metadata: 1
                                                                                                                ExportTypeIdentity: Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.VisualStudioWorkspaceImpl
                Imports: 0
                Exports: 1
                                #1: Contract Name: Microsoft.VisualStudio.Alm.Roslyn.Client.IVisualStudioIntegrationService
                                                Metadata: 1
                                                                ExportTypeIdentity: Microsoft.VisualStudio.Alm.Roslyn.Client.IVisualStudioIntegrationService
 
996: Microsoft.VisualStudio.Alm.Roslyn.Client.VisualStudioIntegrationService (in Microsoft.VisualStudio.CodeSense.Roslyn)
                Metadata Token: 33554436
                Sharing Boundary: none
                IsShared: True
                IsInstantiable: True
                Importing Constructor:
                                Metadata Token: 100663308
                                Arguments: 2
                                                Microsoft.VisualStudio.Alm.Roslyn.Client.VisualStudioIntegrationService (in Microsoft.VisualStudio.CodeSense.Roslyn)
                                                                Declaring Type's Metadata Token: 33554436
                                                                Cardinality: ExactlyOne
                                                                IsExportFactory: False
                                                                IsLazy: False
                                                                IsNonSharedInstanceRequired: False
                                                                SatisfyingExports: 1
                                                                                #1: Contract Name: Microsoft.VisualStudio.Shell.SVsServiceProvider
                                                                                                Exported Type: Microsoft.VisualStudio.Shell.SVsServiceProvider
                                                                                                Exported Type's Assembly: Microsoft.VisualStudio.Shell.Framework, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
                                                                                                Exported Type's Metadata Token: 33554500
                                                                                                Metadata: 1
                                                                                                                ExportTypeIdentity: Microsoft.VisualStudio.Shell.SVsServiceProvider
                                                Microsoft.VisualStudio.Alm.Roslyn.Client.VisualStudioIntegrationService (in Microsoft.VisualStudio.CodeSense.Roslyn)
                                                                Declaring Type's Metadata Token: 33554436
                                                                Cardinality: ExactlyOne
                                                                IsExportFactory: False
                                                                IsLazy: False
                                                                IsNonSharedInstanceRequired: False
                                                                SatisfyingExports: 1
                                                                                #1: Contract Name: Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.VisualStudioWorkspaceImpl
                                                                                                Exported Type: Microsoft.VisualStudio.LanguageServices.RoslynVisualStudioWorkspace
                                                                                                Exported Type's Assembly: Microsoft.VisualStudio.LanguageServices.Implementation, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
                                                                                                Exported Type's Metadata Token: 33554435
                                                                                                Metadata: 1
                                                                                                                ExportTypeIdentity: Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.VisualStudioWorkspaceImpl
                Imports: 0
                Exports: 1
                                #1: Contract Name: Microsoft.VisualStudio.Alm.Roslyn.Client.IVisualStudioIntegrationService
                                                Metadata: 1
                                                                ExportTypeIdentity: Microsoft.VisualStudio.Alm.Roslyn.Client.IVisualStudioIntegrationService

Ported from Bug 294007 by @Pilchie

Composition failure for an import refs to type of the import, not the contract type

Had the following:

        [ImportingConstructor]
        public StartupProjectRegistrar(
            [Import(typeof(IProjectGuidService))]IProjectGuidService2 projectGuidService,
        {
        }

Got the following error:

Microsoft.VisualStudio.ProjectSystem.VS.Debug.StartupProjectRegistrar.ctor(projectGuidService): expected exactly 1 export of Microsoft.VisualStudio.ProjectSystem.VS.IProjectGuidService2 but found 2.
    Microsoft.VisualStudio.Project.VisualC.VCProjectEngine.VCProjectShim
    Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.ProjectNode
   part definition Microsoft.VisualStudio.ProjectSystem.VS.Debug.StartupProjectRegistrar

Expected:

Microsoft.VisualStudio.ProjectSystem.VS.Debug.StartupProjectRegistrar.ctor(projectGuidService): expected exactly 1 export of Microsoft.VisualStudio.ProjectSystem.VS.IProjectGuidService but found 2.
    Microsoft.VisualStudio.Project.VisualC.VCProjectEngine.VCProjectShim
    Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.ProjectNode
   part definition Microsoft.VisualStudio.ProjectSystem.VS.Debug.StartupProjectRegistrar

Should be referring to the contract type of the import, not the identity type.

IProgress<T>.Report never reaches 100%

Consider the minimal sample below. The progress callback never reaches 100%. It works when you have one export. Adding a second one, does not. The last print-out says:
"Scanning MEF assemblies... Step 369 of 370".

It differs even more for large projects. Is this a bug?

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Composition;

namespace MefTest
{
    [Export]
    public class ViewModel
    {
    }

    [Export]
    public class ViewModel2
    {
    }

    public class Listener : IProgress<DiscoveryProgress>
    {
        public void Report(DiscoveryProgress value)
        {
            System.Diagnostics.Debug.WriteLine($"{value.Status} Step {value.CompletedSteps} of {value.TotalSteps}");
        }
    }

    class Program
    {
        static void Main()
        {
            InitMef(new Listener()).Wait();
        }

        private static async Task<ExportProvider> InitMef(IProgress<DiscoveryProgress> progress)
        {
            var discovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(Resolver.DefaultInstance));
            var catalog = ComposableCatalog.Create(Resolver.DefaultInstance)
                .AddParts(await discovery.CreatePartsAsync(GetAssemblies(), progress));

            var config = CompositionConfiguration.Create(catalog);
            var epf = config.CreateExportProviderFactory();
            var exportProvider = epf.CreateExportProvider();

            return exportProvider;
        }

        private static IEnumerable<Assembly> GetAssemblies()
        {
            yield return Assembly.GetExecutingAssembly();
        }
    }
}

Also, why doesn't CreatePartsAsync(Assembly) have an overload for IProgress?

Rejection should prefer the ImportMany site over the Export site

When vs-mef encounters this graph error:

Microsoft.VisualStudio.Text.Editor.Implementation.WpfTextEditorFactoryService.WpfTextViewCreationListeners: is not assignable from exported MEF value Microsoft.PythonTools.Django.Intellisense.TemplateTextViewConnectionListener.
   part definition Microsoft.VisualStudio.Text.Editor.Implementation.WpfTextEditorFactoryService 

EXPECTED

The TemplateTextViewConnectionListener MEF part should be rejected from the graph, as that is where the fault lies.

The graph analysis justification for this may be any or all of the following reasons:

  1. WpfTextEditorFactoryService has the [ImportMany] attribute, suggesting it's in a more vulnerable position to bad actors, and should not be penalized when one exists.
  2. The import site's type identity strings matches the import element type, which is a very strong indicator that it is correct.

ACTUAL

vs-mef throws out the WpfTextEditorFactoryService instead.

Importing metadata with Dictionary<string,object> broken

Importing with the concrete type instead of the interface seems to have broken in the master branch (it works in v15.6):

[Import, MefV1.Import]
public Lazy<PartWithExportMetadata, Dictionary<string, object>> ImportingProperty { get; set; }

Flag improper use of [Import] on property with no setter

When [Import] appears on an auto-property with no setter, VS MEF will not be able to set the property at runtime. We should either support this (by some fancy reflection) or define an analyzer that will produce an error in such a case.
The corrective action would be to explicitly add a private set; accessor.

CompositionConfiguration.FindLoops throws ArgumentException

VS failed to launch because a catalog failed to compose, as follows:

LegacySitePackage failed for package [CSharpPackage]Source: 'mscorlib' Description: An item with the same key has already been added.
System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at Microsoft.VisualStudio.Composition.CompositionConfiguration.<FindLoops>d__28.MoveNext()
   at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
   at System.Collections.Generic.List`1.AddRange(IEnumerable`1 collection)
   at Microsoft.VisualStudio.Composition.CompositionConfiguration.Create(ComposableCatalog catalog)
   at Microsoft.VisualStudio.ExtensibilityHosting.VsExportProviderFactory.VsExportProviderFactoryWorker.<>c__DisplayClass14_0.<<SerializeFinalCatalogAsync>b__0>d.MoveNext()   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at Microsoft.VisualStudio.ExtensibilityHosting.VsExportProviderFactory.<GetExportProviderFactoryAsync>d__36.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.ComponentModelHost.ComponentModel.<GetMEFV3ExportProviderInternalAsync>d__50.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.ComponentModelHost.ComponentModel.<GetMEFV3ExportProviderWrapperAsync>d__49.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.Threading.AsyncLazy`1.<>c__DisplayClass13_1.<<GetValueAsync>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.Threading.JoinableTask.CompleteOnCurrentThread()
   at Microsoft.VisualStudio.Threading.JoinableTask`1.CompleteOnCurrentThread()
   at Microsoft.VisualStudio.Threading.JoinableTaskFactory.Run[T](Func`1 asyncMethod, JoinableTaskCreationOptions creationOptions)
   at Microsoft.VisualStudio.Threading.JoinableTaskFactory.Run[T](Func`1 asyncMethod)
   at Microsoft.VisualStudio.ComponentModelHost.ComponentModel.GetLazyValue[T](AsyncLazy`1 lazy)
   at Microsoft.VisualStudio.ComponentModelHost.ComponentModel.GetService[T]()
   at Microsoft.VisualStudio.LanguageServices.Implementation.AbstractEditorFactory..ctor(Package package)
   at Microsoft.VisualStudio.LanguageServices.CSharp.LanguageService.CSharpPackage.CreateEditorFactories()
   at Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService.AbstractPackage`2.Initialize()
   at Microsoft.VisualStudio.LanguageServices.CSharp.LanguageService.CSharpPackage.Initialize()
   at Microsoft.VisualStudio.Shell.Package.Microsoft.VisualStudio.Shell.Interop.IVsPackage.SetSite(IServiceProvider sp)

AppHost: Support for .NET Core targeting apps

When AppHost is installed in a .NET Core targeting application, it fails to scan the $(TargetPath) assembly because it can't load the System.Runtime ref assembly (at least when the MSBuild task runs on .NET Framework).

I suspect the fix for this is to teach the MSBuild Task where to find the .NET Framework runtime version of System.Runtime and load that.

Also: add the right package dependencies to the AppHost package for the other frameworks.

How to detect if cached composition data is obsolete?

Let's say my main assembly has version 1.0.1.0. I serialize its composition data to disk:

await cacheManager.SaveAsync(configuration, stream);

Then I update my assembly version to 1.0.2.0. Finally, I successfully (and a bit unexpectedly) deserialize the composition data from the previously saved cache:

var epf = await cacheManager.LoadExportProviderFactoryAsync(stream, resolver);

I expected this to fail, since the version has changed. Viewing the serialized data, I can see the old version number lurking around. Running the application seems to work, but I guess there could have been a problem if the dependencies had changed.

Not sure how to interpret these findings. What is the expected behavior, and why?

More importantly, is it possible to detect if a serialized cache is obsolete?

Support for .NET Standard

I believe we should be able to target .NET Standard 1.5.

Work is proceeding in the dev/andarno/netstandard branch.

  • Get the library compiling for .NET Standard
  • Get all test dependencies to build on .NET Standard
  • Get the test project itself to build on .NET Standard
  • Get the tests to pass on .NET Standard

Internal interface metadata view proxy generation fails after first assembly

As added in #10, VS MEF claims to support internal metadata view interfaces by telling the CLR to skip visibility checks. We have a test for this, but it turns out the CLR fails when asked to skip visibility checks for the second assembly.

at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)
   at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
   at System.Reflection.Emit.TypeBuilder.CreateTypeInfo()
   at Microsoft.VisualStudio.Composition.MetadataViewGenerator.GenerateInterfaceViewProxyType(Type viewType) in D:\git\MEF\src\Microsoft.VisualStudio.Composition\Configuration\MetadataViewGenerator.cs:line 263
   at Microsoft.VisualStudio.Composition.MetadataViewGenerator.GetMetadataViewFactory(Type viewType) in D:\git\MEF\src\Microsoft.VisualStudio.Composition\Configuration\MetadataViewGenerator.cs:line 127
   at Microsoft.VisualStudio.Composition.ExportMetadataViewInterfaceEmitProxy.MetadataViewProxyProvider.CreateProxy(IReadOnlyDictionary`2 metadata, IReadOnlyDictionary`2 defaultValues, Type metadataViewType) in D:\git\MEF\src\Microsoft.VisualStudio.Composition\Configuration\ExportMetadataViewInterfaceEmitProxy.cs:line 34
   at Microsoft.VisualStudio.Composition.ExportProvider.GetStrongTypedMetadata(IReadOnlyDictionary`2 metadata, Type metadataType) in D:\git\MEF\src\Microsoft.VisualStudio.Composition\ExportProvider.cs:line 550
   at Microsoft.VisualStudio.Composition.RuntimeExportProviderFactory.RuntimeExportProvider.GetValueForImportElement(RuntimePartLifecycleTracker importingPartTracker, RuntimeImport import, RuntimeExport export, Func`3 lazyFactory) in D:\git\MEF\src\Microsoft.VisualStudio.Composition\RuntimeExportProviderFactory+RuntimeExportProvider.cs:line 237
   at Microsoft.VisualStudio.Composition.RuntimeExportProviderFactory.RuntimeExportProvider.GetValueForImportSite(RuntimePartLifecycleTracker importingPartTracker, RuntimeImport import) in D:\git\MEF\src\Microsoft.VisualStudio.Composition\RuntimeExportProviderFactory+RuntimeExportProvider.cs:line 133
   at Microsoft.VisualStudio.Composition.RuntimeExportProviderFactory.RuntimeExportProvider.RuntimePartLifecycleTracker.SatisfyImports() in D:\git\MEF\src\Microsoft.VisualStudio.Composition\RuntimeExportProviderFactory+RuntimeExportProvider.cs:line 549
   at Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.SatisfyImmediateImports() in D:\git\MEF\src\Microsoft.VisualStudio.Composition\ExportProvider.cs:line 1202
   at Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveNext(PartLifecycleState nextState) in D:\git\MEF\src\Microsoft.VisualStudio.Composition\ExportProvider.cs:line 1263
   at Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveToState(PartLifecycleState requiredState) in D:\git\MEF\src\Microsoft.VisualStudio.Composition\ExportProvider.cs:line 1335
   at Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.GetValueReadyToExpose() in D:\git\MEF\src\Microsoft.VisualStudio.Composition\ExportProvider.cs:line 1058
   at Microsoft.VisualStudio.Composition.ExportProvider.<>c__DisplayClass53_0.<CreateExport>b__0() in D:\git\MEF\src\Microsoft.VisualStudio.Composition\ExportProvider.cs:line 462
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at System.Lazy`1.get_Value()
   at Microsoft.VisualStudio.Composition.Export.get_Value() in D:\git\MEF\src\Microsoft.VisualStudio.Composition\Export.cs:line 54
   at Microsoft.VisualStudio.Composition.ExportProvider.<>c__DisplayClass70_1`2.<GetExports>b__1() in D:\git\MEF\src\Microsoft.VisualStudio.Composition\ExportProvider.cs:line 814
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at System.Lazy`1.get_Value()
   at Microsoft.VisualStudio.Composition.ExportProvider.GetExportedValue[T]() in D:\git\MEF\src\Microsoft.VisualStudio.Composition\ExportProvider.cs:line 256
   at Microsoft.VisualStudio.Composition.Tests.TestUtilities.V3ContainerWrapper.GetExportedValue[T]() in D:\git\MEF\src\tests\Microsoft.VisualStudio.Composition.Tests\TestUtilities.cs:line 715
   at Microsoft.VisualStudio.Composition.Tests.ExportMetadataTests.ThreadSafetyTestForInternalInterfaceProxyGeneration_2Then1(IContainer container) in D:\git\MEF\src\tests\Microsoft.VisualStudio.Composition.Tests\ExportMetadataTests.cs:line 161

Unstable test: LazyOfSharedPartConstructsOnlyOneInstanceAcrossThreads

The LazyOfSharedPartConstructsOnlyOneInstanceAcrossThreads test has failed in at least two different builds.

See one such failure here:

   V1 [FAIL]
      Assert.Equal() Failure
      Expected: 1
      Actual:   2
      Stack Trace:
        src\tests\Microsoft.VisualStudio.Composition.Tests\ThreadSafetyTests.cs(82,0): at Microsoft.VisualStudio.Composition.Tests.ThreadSafetyTests.<LazyOfSharedPartConstructsOnlyOneInstanceAcrossThreads>d__3.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
    V2 [FAIL]
      Assert.Equal() Failure
      Expected: 1
      Actual:   2
      Stack Trace:
        src\tests\Microsoft.VisualStudio.Composition.Tests\ThreadSafetyTests.cs(82,0): at Microsoft.VisualStudio.Composition.Tests.ThreadSafetyTests.<LazyOfSharedPartConstructsOnlyOneInstanceAcrossThreads>d__3.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.GetResult()

Heap regression in master branch

  • Check that we are interning string and AssemblyName instances when deserializing from the cache.
  • Convert the *Ref structs to classes as they are significantly larger than 16 bytes and they appear in many other types (transitively or directly).

Questions on using/moving from standard System.Composition

Our system is currently using System.Composition for MEF and we'd like to add the caching feature using this package. What isn't clear is how to get this package to work with out existing setup. Here's some issues/questions:

  1. We're using the AggregateCatalog that has both AssemblyCatalogs and a DirectoryCatalog. How do we use a DirectoryCatalog with the ComposableCatalog?

  2. We use an ExportFactory with an ImportMany attribute to create many instances of an exported part. Can we continue to use the ExportFactory or is there another construct that replaces it in this package?

  3. Is there more documentation on the caching? I assume the ExportProviderFactory.LoadDefault() loads from cache, what if things haven't been cached? Where is the actual cache located?

  4. Is there an example project somewhere that has a typical System.Composition MEF scenario and how VS MEF works with it or in place of it?

Thanks!

ImportMany failure at runtime instead of composition time

Consider the following scenario having ImportMany over mixed scoped/unscoped exports

public interface IMessageHandler { }

[Export(typeof(IMessageHandler))]
public class UniqueMessageHandler : IMessageHandler { }

[Export(typeof(IMessageHandler))]
[Shared]
public class GlobalMessageHandler : IMessageHandler { }

[Export(typeof(IMessageHandler))]
[Shared("somewhere")]
public class ScopedMessageHandler : IMessageHandler { }

[Export]
public class Helper1
{
    [ImportMany]
    public ICollection<Lazy<IMessageHandler>> Handlers { get; set; }
}

[Export]
public class Helper2
{
    [Import]
    public Lazy<Helper1> LazyHelper { get; set; }
}

Observed behavior:

  • in MEF v1 this cannot happen because shared scopes do not exist
  • in MEF v2 (the nuget version)
    • Helper1.Handlers gets populated with all 3 IMessageHandler exports (probably a bug because now application code sees metadata which it should have never seen)
    • fails at runtime when resolving Lazy<IMessageHandler>.Value on the scoped import
  • in MEF v3 (vs-mef, this project)
    • Helper1 fails to resolve at runtime because it realizes one of the 3 IMessageHandlers is scoped, so it doesn't bother to construct a Lazy import around it. (This is good, even though the failure at runtime is kinda late.)
    • Helper2.LazyHelper gets populated with a Helper1 export even though it will fail to resolve at runtime when calling Lazy<Helper1>.Value (This is bad because it delays failure and application code inspecting metadata doesn't know the import is invalid.)

Expected behavior:

  • since Helper1 can never be constructed it should have been pulled from the composition graph and generated a corresponding entry in the CompositionErrors

PS: The original scenario was someone marking an export as scoped in an extension assembly, causing random application failures because the ImportMany was lazily resolved. Was kinda hard to root cause.

Offer an API to remove parts from ComposableCatalog

Although the workaround exists where a new ComposableCatalog can be created with a subset of the parts from a prior catalog, it would be more convenient if a method were offered that returns a new catalog with the parts removed.

Potentially the removal criteria could be based on part type or export.

Error when encountering a null ImportMany "collection" should be a little more obvious

Had the following code:

        public UnconfiguredProjectContextProvider()
        {
        }

        [ImportMany]
        public OrderPrecedenceImportCollection<IProjectGuidService> ProjectGuidServices
        {
            get;
        }

Notice I hadn't instantiated the collection above, and got the following:

Microsoft.VisualStudio.Composition.CompositionFailedException: Import "Microsoft.VisualStudio.ProjectSystem.VS.LanguageServices.UnconfiguredProjectContextProvider.ProjectGuidServices" could not be satisfied. ---> Microsoft.VisualStudio.Composition.CompositionFailedException: Unable to instantiate custom import collection type.
   at Microsoft.VisualStudio.Composition.RuntimeExportProviderFactory.RuntimeExportProvider.GetValueForImportSite(RuntimePartLifecycleTracker importingPartTracker, RuntimeImport import)
   at Microsoft.VisualStudio.Composition.RuntimeExportProviderFactory.RuntimeExportProvider.RuntimePartLifecycleTracker.SatisfyImports()
   --- End of inner exception stack trace ---
   at Microsoft.VisualStudio.Composition.RuntimeExportProviderFactory.RuntimeExportProvider.RuntimePartLifecycleTracker.SatisfyImports()
   at Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.SatisfyImmediateImports()
   at Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveNext(PartLifecycleState nextState)
   at Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.GetValueReadyToExpose()
   at Microsoft.VisualStudio.Composition.RuntimeExportProviderFactory.RuntimeExportProvider.<>c__DisplayClass15_0.<GetExportedValueHelper>b__0()
   at Microsoft.VisualStudio.Composition.DelegateServices.<>c__DisplayClass2_0`1.<As>b__0()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()

It would be helpful to provide a little more info here - you can't instantiate a new version of the collection here, but that's not the problem in this case - we forgot to instantiate it.

MEFv2 attributes make importing SAsyncServiceProvider hard

In the following two MEF parts running in VS, the MEFv1Part gets both properties set to a non-null value, while the MEFv2Part only has the second property set to a non-null value.

Why is that? Is it by design of how MEFv2 attributes behave or a bug in VS-MEF?

        [MEFv1.Export]
        public class MEFv1Part
        {
            [MEFv1.Import(typeof(SAsyncServiceProvider), AllowDefault = true)]
            public Microsoft.VisualStudio.Shell.IAsyncServiceProvider AsyncServiceProvider { get; set; }

            [MEFv1.Import(typeof(SAsyncServiceProvider), AllowDefault = true)]
            public object AsyncServiceProvider3 { get; set; }
        }

        [MEFv2.Export]
        public class MEFv2Part
        {
            [MEFv2.Import("Microsoft.VisualStudio.Shell.Interop.SAsyncServiceProvider", AllowDefault = true)]
            public Microsoft.VisualStudio.Shell.IAsyncServiceProvider AsyncServiceProvider { get; set; }

            [MEFv2.Import("Microsoft.VisualStudio.Shell.Interop.SAsyncServiceProvider", AllowDefault = true)]
            public object AsyncServiceProvider3 { get; set; }
        }

random ArgumentNullException in VS MEF when using VS

It is a random problem reported by customers, and it has random stack in the product side (random place accessing MEF), but share the same stack similar to the one I pasted here.

After looking into the MEF code, I think it is a MEF code bug, independent to the composition. The only explanation I can get is that the bug is inside RuntimeImport.IsLazy implementation. It runs into a race condition, because Nullable is not thread safe. When one thread computed the value and sets the value to true, in the split time, another thread can see the value has been set, and is false, which leads it to think valueFunction is null.

Microsoft.Requires.NotNull[T](T,String)
Microsoft.VisualStudio.Composition.RuntimeExportProviderFactory.RuntimeExportProvider.GetValueForImportElement(RuntimePartLifecycleTracker,RuntimeImport,RuntimeExport,Func`3)
Microsoft.VisualStudio.Composition.RuntimeExportProviderFactory.RuntimeExportProvider.GetValueForImportSite(RuntimePartLifecycleTracker,RuntimeImport)
Microsoft.VisualStudio.Composition.RuntimeExportProviderFactory.RuntimeExportProvider.RuntimePartLifecycleTracker.SatisfyImports()
Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.SatisfyImmediateImports()
Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveNext(PartLifecycleState)
Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveToState(PartLifecycleState)
Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveToStateTransitively(PartLifecycleState,HashSet`1)
Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveToStateTransitively(PartLifecycleState,HashSet`1)
Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveToStateTransitively(PartLifecycleState,HashSet`1)
Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveToStateTransitively(PartLifecycleState,HashSet`1)
Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveToStateTransitively(PartLifecycleState,HashSet`1)
Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveNext(PartLifecycleState)
Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.MoveToState(PartLifecycleState)
Microsoft.VisualStudio.Composition.ExportProvider.PartLifecycleTracker.GetValueReadyToExpose()
Microsoft.VisualStudio.Composition.RuntimeExportProviderFactory.RuntimeExportProvider.<>c__DisplayClass15_0.<GetExportedValueHelper>b__0()
Microsoft.VisualStudio.Composition.DelegateServices.<>c__DisplayClass2_0`1.<As>b__0()
System.Lazy`1.CreateValue()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw

TypeRef.Equals should check assembly MVID

Currently TypeRef.Equals does not check the MVID of its assembly, just the full assembly name. This is inconsistent with the check that TryUseFastReflection uses. Meaning that cache equality comparisions can return true but slow reflection would still have to be used.

Documentation and samples

Hi,

I'm somewhat familiar with the old MEF 1 from years ago, and now wanting to use MEF for a standard 'plugins'-type scenario, and I prefer to use the latest ways.

I just wanted to know whether the demo at AArnott/VSMefSample is still valid for me to study and learn (it's approx a year-and-a-half old now). Can you provide other modern examples, or is that good enough?

I'm mainly asking because I noticed the code in the Exported classes use the (now very old) System.Composition namespace, whereas others use the vs-mef namespaces.

Thank-you.

Difference between V1MEF for Properties on metadata views with default value attribute

VS MEF does not handle properties with the default value attribute on metadata views the same way that V1 of MEF handles them. Specifically if the metadata view is tagged with the attribute specifying a metadataview implementation, v1 of MEF ignores any export metadata associated with properties that have a default value attribute.

Our team really wants to update to VS MEF, but we have some unique scenarios where a lot of our code uses this pattern of setting the export metadata to something that is a different data type than the property itself, and we interpret that to set the property correctly in the constructor of our metadata view implementation. Currently in VS MEF this fails. The problem is the check in ImportMetadataViewConstraint.IsSatisfiedBy. In this check the constraint determines there is export metadata, and it makes sure it can be assigned to the property. I already have what I thought seemed like a reasonable fix in my fork of the v16.0 branch. I also added tests. Originally I didn't think you guys were accepting pull requests, but I was able to create one so I guess we'll see what happens ๐Ÿ˜Š. If you are accepting them, you might want to update your documentation about contributions.

Support for [TypeForwardedTo]

From my observations VSMEF doesn't seem to unify types which are type forwarded?

For instance, you have SourceAssembly1 with Interface1. ProjectA references SourceAssembly1 and has [assembly:TypeForwardedTo(typeof(Interface1))]. ProjectB references ProjectA and defines TypeB : Interface1.

At runtime if I have an [Import] Interface1 I1 it doesn't seem to get satisfied with:

I1: is not assignable from exported MEF value TypeB.

Not saying this is a bug, but just wanted to clarify the design: is this even supposed to work? Should type forwarders be followed and unified?

Avoid memory leak for IDisposable/NonShared exports

Consider the sample below. When the exported type implements IDisposable the container keeps a reference to all created values, even if they are non-shared. This easily causes significant memory leaks.

What is the recommended pattern here?

using System;
using System.ComponentModel.Composition;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Composition;
using CreationPolicy = System.ComponentModel.Composition.CreationPolicy;

namespace MefTest
{
    [Export(typeof(ViewModel)), PartCreationPolicy(CreationPolicy.NonShared)]
    public class ViewModel : IDisposable
    {
        private byte[] bytes;
        public ViewModel() => bytes = new byte[100000]; // Leak
        public void Dispose() {}
    }

    class Program
    {
        static void Main(string[] args)
        {
            var t = InitMef();
            t.Wait();

            var container = t.Result;

            for (var i = 0; i < 100; i++)
            {
                var model = container.GetExportedValue<ViewModel>();
                model.Dispose(); // Container keeps a reference here!
            }

            // NOTE: I want to keep my container.
            // How do I release the memory allocated above?
            // container.Dispose();
        }

        private static async Task<ExportProvider> InitMef()
        {
            var discovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(Resolver.DefaultInstance));

            var catalog = ComposableCatalog.Create(Resolver.DefaultInstance)
                .AddParts(await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly()))
                .WithCompositionService();

            var config = CompositionConfiguration.Create(catalog);
            var epf = config.CreateExportProviderFactory();
            var exportProvider = epf.CreateExportProvider();

            return exportProvider;
        }
    }
}

ExportProvider.GetExports loads assemblies (non-lazily) when members are exported instead of types

This line calls RuntimeExport.Member which forces the load of the containing assembly. Nearby lines do the same thing.

https://github.com/Microsoft/vs-mef/blob/96ebcb19fed7e784a30a282e635c214a10b45194/src/Microsoft.VisualStudio.Composition/RuntimeExportProviderFactory%2BRuntimeExportProvider.cs#L67

We should add a unit test for lazy assembly loading that includes exports applied to members (we probably only test exported types right now) and then go fix this.

Putting an ImportMany on a non-collection type, results in InvalidOperationException

From: dotnet/roslyn#25212.

Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Snippets
    ' HACK: The Export attribute (As ISnippetInfoService) is used by EditorTestApp to create this
    ' SnippetInfoService on the UI thread.
    <Export(GetType(ISnippetInfoService))>
    <ExportLanguageService(GetType(ISnippetInfoService), LanguageNames.VisualBasic), [Shared]>
    Friend Class VisualBasicSnippetInfoService
        Inherits AbstractSnippetInfoService
 
        <ImportingConstructor>
        Public Sub New(serviceProvider As SVsServiceProvider, <ImportMany> listenerProvider As IAsynchronousOperationListenerProvider)
            MyBase.New(serviceProvider, Guids.VisualBasicDebuggerLanguageId, listenerProvider)
        End Sub
    End Class
End Namespace
Microsoft.VisualStudio.Composition.PartDiscoveryException: Failure while scanning type "Microsoft.VisualStudio.LanguageServices.VisualBasic.Snippets.VisualBasicSnippetInfoService". ---> System.InvalidOperationException: Sequence contains no elements
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
   at Microsoft.VisualStudio.Composition.PartDiscovery.GetElementTypeFromMany(Type type)
   at Microsoft.VisualStudio.Composition.PartDiscovery.GetTypeIdentityFromImportingType(Type type, Boolean importMany)
   at Microsoft.VisualStudio.Composition.AttributedPartDiscovery.TryCreateImportDefinition(Type importingType, ICustomAttributeProvider member, ImmutableHashSet`1 importConstraints, ImportDefinition& importDefinition)
   at Microsoft.VisualStudio.Composition.AttributedPartDiscovery.CreateImport(ParameterInfo parameter, ImmutableHashSet`1 importConstraints)
   at Microsoft.VisualStudio.Composition.AttributedPartDiscovery.CreatePart(Type partType, Boolean typeExplicitlyRequested)
   at Microsoft.VisualStudio.Composition.PartDiscovery.CombinedPartDiscovery.CreatePart(Type partType, Boolean typeExplicitlyRequested)
   at Microsoft.VisualStudio.Composition.PartDiscovery.<>c__DisplayClass27_0.<CreateDiscoveryBlockChain>b__0(Type type)
   --- End of inner exception stack trace 

Are there along life support and enhancement?

First, I'm a fan of MEF, and very happy to see it backs (as anthor form).
Can anyone in the team confirm that: Are there along life support and enhancement, as a full framework, like MEF was?

AppHost package enhancements

  1. Binding redirects for VS MEF's own ref assemblies from 15.0->16.0 (including the NetFx attributes assembly)
  2. Support for supplying custom lists of MEF catalogs and additional ref assemblies from MEF catalogs.
  3. Support incremental clean by adding the cache file to the WrittenFiles list (or whatever it's called).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.