提交 72ec3274 编写于 作者: J Jason Malinowski

Add MEF metadata to IDeferredQuickInfoContentToFrameworkElementConverter

When I added this interface, I had the implementations expose their
applicable type not by metadata, but by simply calling a method on
the instance. This is problematic if the implementation is in a
different assembly as we'll load it too early. This is causing F#
to load when they shouldn't.

This is intended as a temporary shim that fixes the perf load for
the F# case (the only current exporter of these outside the Roslyn
repo itself) without forcing an interface change. This will get deleted
soon enough once we migrate to newer Quick Info APIs.
上级 132b91d1
......@@ -13,6 +13,7 @@
namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{
[Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))]
[QuickInfoConverterMetadata(typeof(ClassifiableDeferredContent))]
class ClassifiableDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter
{
private readonly ClassificationTypeMap _typeMap;
......
......@@ -14,6 +14,7 @@
namespace Microsoft.CodeAnalysis.Editor.QuickInfo.Converters
{
[Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))]
[QuickInfoConverterMetadata(typeof(DocumentationCommentDeferredContent))]
internal sealed class DocumentationCommentDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter
{
private readonly ClassificationTypeMap _typeMap;
......
......@@ -13,6 +13,7 @@
namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{
[Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))]
[QuickInfoConverterMetadata(typeof(ProjectionBufferDeferredContent))]
class ProjectionBufferDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter
{
private readonly IProjectionBufferFactoryService _projectionBufferFactoryService;
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.Composition;
namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{
[MetadataAttribute]
internal sealed class QuickInfoConverterMetadataAttribute : Attribute
{
public QuickInfoConverterMetadataAttribute(Type deferredType)
{
DeferredTypeFullName = deferredType.FullName;
}
public string DeferredTypeFullName { get; }
}
}
......@@ -10,6 +10,7 @@
namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{
[Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))]
[QuickInfoConverterMetadata(typeof(QuickInfoDisplayDeferredContent))]
class QuickInfoDisplayDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter
{
public FrameworkElement CreateFrameworkElement(IDeferredQuickInfoContent deferredContent, DeferredContentFrameworkElementFactory factory)
......
......@@ -11,6 +11,7 @@
namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{
[Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))]
[QuickInfoConverterMetadata(typeof(SymbolGlyphDeferredContent))]
class SymbolGlyphDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter
{
public FrameworkElement CreateFrameworkElement(IDeferredQuickInfoContent deferredContent, DeferredContentFrameworkElementFactory factory)
......
......@@ -3,24 +3,53 @@
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows;
using Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{
[Export]
internal class DeferredContentFrameworkElementFactory
{
private readonly Dictionary<Type, IDeferredQuickInfoContentToFrameworkElementConverter> _convertersByType;
private readonly Dictionary<string, Lazy<IDeferredQuickInfoContentToFrameworkElementConverter>> _convertersByTypeFullName
= new Dictionary<string, Lazy<IDeferredQuickInfoContentToFrameworkElementConverter>>();
private readonly IEnumerable<Lazy<IDeferredQuickInfoContentToFrameworkElementConverter>> _convertersWithoutMetadata;
[ImportingConstructor]
public DeferredContentFrameworkElementFactory([ImportMany] IEnumerable<IDeferredQuickInfoContentToFrameworkElementConverter> converters)
public DeferredContentFrameworkElementFactory(
[ImportMany] IEnumerable<Lazy<IDeferredQuickInfoContentToFrameworkElementConverter, IQuickInfoConverterMetadata>> converters,
[ImportMany] IEnumerable<Lazy<IDeferredQuickInfoContentToFrameworkElementConverter>> convertersWithoutMetadata)
{
_convertersByType = converters.ToDictionary(c => c.GetApplicableType());
_convertersByTypeFullName = converters.ToDictionary(
lazy => lazy.Metadata.DeferredTypeFullName,
lazy => (Lazy<IDeferredQuickInfoContentToFrameworkElementConverter>)lazy);
_convertersWithoutMetadata = convertersWithoutMetadata;
}
internal FrameworkElement CreateElement(IDeferredQuickInfoContent deferredContent)
{
return _convertersByType[deferredContent.GetType()].CreateFrameworkElement(deferredContent, this);
var deferredContentFullName = deferredContent.GetType().FullName;
Lazy<IDeferredQuickInfoContentToFrameworkElementConverter> converter;
if (!_convertersByTypeFullName.TryGetValue(deferredContentFullName, out converter))
{
// The content must be of a type we didn't have MEF deferred metadata for. Realize the
// ones without MEF metadata, forcing everything to load.
foreach (var converterWithoutMetadata in _convertersWithoutMetadata)
{
_convertersByTypeFullName[converterWithoutMetadata.Value.GetApplicableType().FullName] =
new Lazy<IDeferredQuickInfoContentToFrameworkElementConverter>(() => converterWithoutMetadata.Value);
}
Contract.ThrowIfFalse(_convertersByTypeFullName.TryGetValue(deferredContentFullName, out converter));
}
return converter.Value.CreateFrameworkElement(deferredContent, this);
}
internal interface IQuickInfoConverterMetadata
{
string DeferredTypeFullName { get; }
}
}
}
......@@ -111,7 +111,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
<WpfFact(), WorkItem(1106729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1106729")>
Public Sub PresenterUpdatesExistingSessionIfNotDismissed()
Dim broker = New Mock(Of IQuickInfoBroker)()
Dim frameworkElementFactory = New DeferredContentFrameworkElementFactory({})
Dim frameworkElementFactory = New DeferredContentFrameworkElementFactory({}, {})
Dim presenter As IIntelliSensePresenter(Of IQuickInfoPresenterSession, IQuickInfoSession) = New QuickInfoPresenter(broker.Object, frameworkElementFactory)
Dim mockEditorSession = New Mock(Of IQuickInfoSession)
mockEditorSession.Setup(Function(m) m.IsDismissed).Returns(False)
......@@ -130,7 +130,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
brokerSession.Setup(Function(m) m.Properties).Returns(New PropertyCollection())
broker.Setup(Function(m) m.CreateQuickInfoSession(It.IsAny(Of ITextView), It.IsAny(Of ITrackingPoint), It.IsAny(Of Boolean))).Returns(brokerSession.Object)
Dim frameworkElementFactory = New DeferredContentFrameworkElementFactory({})
Dim frameworkElementFactory = New DeferredContentFrameworkElementFactory({}, {})
Dim presenter As IIntelliSensePresenter(Of IQuickInfoPresenterSession, IQuickInfoSession) = New QuickInfoPresenter(broker.Object, frameworkElementFactory)
Dim mockEditorSession = New Mock(Of IQuickInfoSession)
mockEditorSession.Setup(Function(m) m.IsDismissed).Returns(True)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册