提交 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 @@ ...@@ -13,6 +13,7 @@
namespace Microsoft.CodeAnalysis.Editor.QuickInfo namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{ {
[Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))] [Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))]
[QuickInfoConverterMetadata(typeof(ClassifiableDeferredContent))]
class ClassifiableDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter class ClassifiableDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter
{ {
private readonly ClassificationTypeMap _typeMap; private readonly ClassificationTypeMap _typeMap;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
namespace Microsoft.CodeAnalysis.Editor.QuickInfo.Converters namespace Microsoft.CodeAnalysis.Editor.QuickInfo.Converters
{ {
[Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))] [Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))]
[QuickInfoConverterMetadata(typeof(DocumentationCommentDeferredContent))]
internal sealed class DocumentationCommentDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter internal sealed class DocumentationCommentDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter
{ {
private readonly ClassificationTypeMap _typeMap; private readonly ClassificationTypeMap _typeMap;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
namespace Microsoft.CodeAnalysis.Editor.QuickInfo namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{ {
[Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))] [Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))]
[QuickInfoConverterMetadata(typeof(ProjectionBufferDeferredContent))]
class ProjectionBufferDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter class ProjectionBufferDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter
{ {
private readonly IProjectionBufferFactoryService _projectionBufferFactoryService; 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 @@ ...@@ -10,6 +10,7 @@
namespace Microsoft.CodeAnalysis.Editor.QuickInfo namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{ {
[Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))] [Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))]
[QuickInfoConverterMetadata(typeof(QuickInfoDisplayDeferredContent))]
class QuickInfoDisplayDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter class QuickInfoDisplayDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter
{ {
public FrameworkElement CreateFrameworkElement(IDeferredQuickInfoContent deferredContent, DeferredContentFrameworkElementFactory factory) public FrameworkElement CreateFrameworkElement(IDeferredQuickInfoContent deferredContent, DeferredContentFrameworkElementFactory factory)
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
namespace Microsoft.CodeAnalysis.Editor.QuickInfo namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{ {
[Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))] [Export(typeof(IDeferredQuickInfoContentToFrameworkElementConverter))]
[QuickInfoConverterMetadata(typeof(SymbolGlyphDeferredContent))]
class SymbolGlyphDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter class SymbolGlyphDeferredContentConverter : IDeferredQuickInfoContentToFrameworkElementConverter
{ {
public FrameworkElement CreateFrameworkElement(IDeferredQuickInfoContent deferredContent, DeferredContentFrameworkElementFactory factory) public FrameworkElement CreateFrameworkElement(IDeferredQuickInfoContent deferredContent, DeferredContentFrameworkElementFactory factory)
......
...@@ -3,24 +3,53 @@ ...@@ -3,24 +3,53 @@
using System.ComponentModel.Composition; using System.ComponentModel.Composition;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.QuickInfo namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{ {
[Export] [Export]
internal class DeferredContentFrameworkElementFactory 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] [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) 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 ...@@ -111,7 +111,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
<WpfFact(), WorkItem(1106729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1106729")> <WpfFact(), WorkItem(1106729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1106729")>
Public Sub PresenterUpdatesExistingSessionIfNotDismissed() Public Sub PresenterUpdatesExistingSessionIfNotDismissed()
Dim broker = New Mock(Of IQuickInfoBroker)() 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 presenter As IIntelliSensePresenter(Of IQuickInfoPresenterSession, IQuickInfoSession) = New QuickInfoPresenter(broker.Object, frameworkElementFactory)
Dim mockEditorSession = New Mock(Of IQuickInfoSession) Dim mockEditorSession = New Mock(Of IQuickInfoSession)
mockEditorSession.Setup(Function(m) m.IsDismissed).Returns(False) mockEditorSession.Setup(Function(m) m.IsDismissed).Returns(False)
...@@ -130,7 +130,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense ...@@ -130,7 +130,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
brokerSession.Setup(Function(m) m.Properties).Returns(New PropertyCollection()) 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) 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 presenter As IIntelliSensePresenter(Of IQuickInfoPresenterSession, IQuickInfoSession) = New QuickInfoPresenter(broker.Object, frameworkElementFactory)
Dim mockEditorSession = New Mock(Of IQuickInfoSession) Dim mockEditorSession = New Mock(Of IQuickInfoSession)
mockEditorSession.Setup(Function(m) m.IsDismissed).Returns(True) 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.
先完成此消息的编辑!
想要评论请 注册