1
// -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
5 using System
.Collections
.Generic
;
6 using System
.ComponentModel
.Composition
.Hosting
;
7 using System
.ComponentModel
.Composition
.Primitives
;
8 using System
.Diagnostics
.CodeAnalysis
;
9 using System
.Globalization
;
11 using System
.Reflection
;
12 using Microsoft
.Internal
;
13 using Microsoft
.Internal
.Collections
;
15 namespace System
.ComponentModel
.Composition
17 // Provides helpers for creating and dealing with Exports
18 internal static partial class ExportServices
20 private static readonly MethodInfo _createStronglyTypedLazyOfTM
= typeof(ExportServices
).GetMethod("CreateStronglyTypedLazyOfTM", BindingFlags
.NonPublic
| BindingFlags
.Static
);
21 private static readonly MethodInfo _createStronglyTypedLazyOfT
= typeof(ExportServices
).GetMethod("CreateStronglyTypedLazyOfT", BindingFlags
.NonPublic
| BindingFlags
.Static
);
22 private static readonly MethodInfo _createSemiStronglyTypedLazy
= typeof(ExportServices
).GetMethod("CreateSemiStronglyTypedLazy", BindingFlags
.NonPublic
| BindingFlags
.Static
);
23 private static readonly MethodInfo _createStronglyTypedExportFactoryOfT
= typeof(ExportServices
).GetMethod("CreateStronglyTypedExportFactoryOfT", BindingFlags
.NonPublic
| BindingFlags
.Static
);
24 private static readonly MethodInfo _createStronglyTypedExportFactoryOfTM
= typeof(ExportServices
).GetMethod("CreateStronglyTypedExportFactoryOfTM", BindingFlags
.NonPublic
| BindingFlags
.Static
);
26 internal static readonly Type DefaultMetadataViewType
= typeof(IDictionary
<string, object>);
27 internal static readonly Type DefaultExportedValueType
= typeof(object);
29 internal static bool IsDefaultMetadataViewType(Type metadataViewType
)
31 Assumes
.NotNull(metadataViewType
);
33 // Consider all types that IDictionary<string, object> derives from, such
34 // as ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
35 // and IEnumerable, as default metadata view
36 return metadataViewType
.IsAssignableFrom(DefaultMetadataViewType
);
39 internal static bool IsDictionaryConstructorViewType(Type metadataViewType
)
41 Assumes
.NotNull(metadataViewType
);
43 // Does the view type have a constructor that is a Dictionary<string, object>
44 return metadataViewType
.GetConstructor(BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
,
46 new Type
[] { typeof(IDictionary<string, object>) }
,
47 new ParameterModifier
[0]) != null;
50 internal static Func
<Export
, object> CreateStronglyTypedLazyFactory(Type exportType
, Type metadataViewType
)
52 MethodInfo genericMethod
= null;
53 if (metadataViewType
!= null)
55 genericMethod
= _createStronglyTypedLazyOfTM
.MakeGenericMethod(exportType
?? ExportServices
.DefaultExportedValueType
, metadataViewType
);
59 genericMethod
= _createStronglyTypedLazyOfT
.MakeGenericMethod(exportType
?? ExportServices
.DefaultExportedValueType
);
61 Assumes
.NotNull(genericMethod
);
62 return (Func
<Export
, object>)Delegate
.CreateDelegate(typeof(Func
<Export
, object>), genericMethod
);
65 internal static Func
<Export
, Lazy
<object, object>> CreateSemiStronglyTypedLazyFactory(Type exportType
, Type metadataViewType
)
67 MethodInfo genericMethod
= _createSemiStronglyTypedLazy
.MakeGenericMethod(
68 exportType
?? ExportServices
.DefaultExportedValueType
,
69 metadataViewType
?? ExportServices
.DefaultMetadataViewType
);
70 Assumes
.NotNull(genericMethod
);
71 return (Func
<Export
, Lazy
<object, object>>)Delegate
.CreateDelegate(typeof(Func
<Export
, Lazy
<object,object>>), genericMethod
);
74 [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
75 internal static Lazy
<T
, M
> CreateStronglyTypedLazyOfTM
<T
, M
>(Export export
)
77 IDisposable disposable
= export
as IDisposable
;
78 if (disposable
!= null)
80 return new DisposableLazy
<T
, M
>(
81 () => ExportServices
.GetCastedExportedValue
<T
>(export
),
82 AttributedModelServices
.GetMetadataView
<M
>(export
.Metadata
),
87 return new Lazy
<T
, M
>(
88 () => ExportServices
.GetCastedExportedValue
<T
>(export
),
89 AttributedModelServices
.GetMetadataView
<M
>(export
.Metadata
),
94 [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
95 internal static Lazy
<T
> CreateStronglyTypedLazyOfT
<T
>(Export export
)
97 IDisposable disposable
= export
as IDisposable
;
98 if (disposable
!= null)
100 return new DisposableLazy
<T
>(
101 () => ExportServices
.GetCastedExportedValue
<T
>(export
),
106 return new Lazy
<T
>(() => ExportServices
.GetCastedExportedValue
<T
>(export
), false);
111 [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
112 internal static Lazy
<object, object> CreateSemiStronglyTypedLazy
<T
, M
>(Export export
)
114 IDisposable disposable
= export
as IDisposable
;
115 if (disposable
!= null)
117 return new DisposableLazy
<object, object>(
118 () => ExportServices
.GetCastedExportedValue
<T
>(export
),
119 AttributedModelServices
.GetMetadataView
<M
>(export
.Metadata
),
124 return new Lazy
<object, object>(
125 () => ExportServices
.GetCastedExportedValue
<T
>(export
),
126 AttributedModelServices
.GetMetadataView
<M
>(export
.Metadata
),
132 internal static Func
<Export
, object> CreateStronglyTypedExportFactoryFactory(Type exportType
, Type metadataType
, ConstructorInfo constructor
)
134 MethodInfo genericMethod
= null;
135 if (metadataType
== null)
137 genericMethod
= _createStronglyTypedExportFactoryOfT
.MakeGenericMethod(exportType
);
141 genericMethod
= _createStronglyTypedExportFactoryOfTM
.MakeGenericMethod(exportType
, metadataType
);
144 Assumes
.NotNull(genericMethod
);
145 Func
<Export
, ConstructorInfo
, object> exportFactoryFactory
= (Func
<Export
, ConstructorInfo
, object>)Delegate
.CreateDelegate(typeof(Func
<Export
, ConstructorInfo
, object>), genericMethod
);
146 return (e
) => exportFactoryFactory
.Invoke(e
, constructor
);
149 private static Tuple
<T
, Action
> GetExportLifetimeContextFromExport
<T
>(Export export
)
152 Action disposeAction
;
153 IDisposable disposable
= null;
155 CatalogExportProvider
.PartCreatorExport partCreatorExport
= export
as CatalogExportProvider
.PartCreatorExport
;
157 if (partCreatorExport
!= null)
159 // PartCreatorExport is the more optimized route
160 Export exportProduct
= partCreatorExport
.CreateExportProduct();
161 exportedValue
= GetCastedExportedValue
<T
>(exportProduct
);
162 disposable
= exportProduct
as IDisposable
;
166 // If it comes from somewhere else we walk through the ComposablePartDefinition
167 var factoryPartDefinition
= GetCastedExportedValue
<ComposablePartDefinition
>(export
);
168 var part
= factoryPartDefinition
.CreatePart();
169 var exportDef
= factoryPartDefinition
.ExportDefinitions
.Single();
171 exportedValue
= CastExportedValue
<T
>(part
.ToElement(), part
.GetExportedValue(exportDef
));
172 disposable
= part
as IDisposable
;
175 if (disposable
!= null)
177 disposeAction
= () => disposable
.Dispose();
181 disposeAction
= () => { }
;
184 return new Tuple
<T
, Action
>(exportedValue
, disposeAction
);
187 private static object CreateStronglyTypedExportFactoryOfT
<T
>(Export export
, ConstructorInfo constructor
)
189 Func
<Tuple
<T
, Action
>> exportLifetimeContextCreator
= () => ExportServices
.GetExportLifetimeContextFromExport
<T
>(export
);
190 return constructor
.Invoke(new object[] { exportLifetimeContextCreator }
);
193 private static object CreateStronglyTypedExportFactoryOfTM
<T
, M
>(Export export
, ConstructorInfo constructor
)
195 Func
<Tuple
<T
, Action
>> exportLifetimeContextCreator
= () => ExportServices
.GetExportLifetimeContextFromExport
<T
>(export
);
196 return constructor
.Invoke(new object[] { exportLifetimeContextCreator, AttributedModelServices.GetMetadataView<M>(export.Metadata) }
);
199 internal static T GetCastedExportedValue
<T
>(Export export
)
201 return CastExportedValue
<T
>(export
.ToElement(), export
.Value
);
204 internal static T CastExportedValue
<T
>(ICompositionElement element
, object exportedValue
)
206 object typedExportedValue
= null;
208 bool succeeded
= ContractServices
.TryCast(typeof(T
), exportedValue
, out typedExportedValue
);
211 throw new CompositionContractMismatchException(string.Format(CultureInfo
.CurrentCulture
,
212 Strings
.ContractMismatch_ExportedValueCannotBeCastToT
,
217 return (T
)typedExportedValue
;
220 internal static ExportCardinalityCheckResult
CheckCardinality(ImportDefinition definition
, IEnumerable
<Export
> exports
)
222 EnumerableCardinality actualCardinality
= exports
.GetCardinality();
224 switch (actualCardinality
)
226 case EnumerableCardinality
.Zero
:
227 if (definition
.Cardinality
== ImportCardinality
.ExactlyOne
)
229 return ExportCardinalityCheckResult
.NoExports
;
233 case EnumerableCardinality
.TwoOrMore
:
234 if (definition
.Cardinality
.IsAtMostOne())
236 return ExportCardinalityCheckResult
.TooManyExports
;
241 Assumes
.IsTrue(actualCardinality
== EnumerableCardinality
.One
);
246 return ExportCardinalityCheckResult
.Match
;