update MEF to preview 9
[mcs.git] / class / System.ComponentModel.Composition / src / ComponentModel / System / ComponentModel / Composition / ExportServices.cs
blob9aa11951d594366d835d89a4d19536da11781183
1 // -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
4 using System;
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;
10 using System.Linq;
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,
45 Type.DefaultBinder,
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);
57 else
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),
83 disposable);
85 else
87 return new Lazy<T, M>(
88 () => ExportServices.GetCastedExportedValue<T>(export),
89 AttributedModelServices.GetMetadataView<M>(export.Metadata),
90 false);
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),
102 disposable);
104 else
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),
120 disposable);
122 else
124 return new Lazy<object, object>(
125 () => ExportServices.GetCastedExportedValue<T>(export),
126 AttributedModelServices.GetMetadataView<M>(export.Metadata),
127 false
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);
139 else
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)
151 T exportedValue;
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;
164 else
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();
179 else
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);
209 if (!succeeded)
211 throw new CompositionContractMismatchException(string.Format(CultureInfo.CurrentCulture,
212 Strings.ContractMismatch_ExportedValueCannotBeCastToT,
213 element.DisplayName,
214 typeof(T)));
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;
231 break;
233 case EnumerableCardinality.TwoOrMore:
234 if (definition.Cardinality.IsAtMostOne())
236 return ExportCardinalityCheckResult.TooManyExports;
238 break;
240 default:
241 Assumes.IsTrue(actualCardinality == EnumerableCardinality.One);
242 break;
246 return ExportCardinalityCheckResult.Match;