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