update MEF to preview 9
[mcs.git] / class / System.ComponentModel.Composition / src / Composition.Initialization / System / ComponentModel / Composition / Hosting / CompositionHost.cs
blob33d65fd64994d3d202c0e3254ee3b4ffdbcd81a9
1 // -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
4 using System;
5 using System.Globalization;
6 using System.Threading;
7 using System.ComponentModel.Composition.Primitives;
8 namespace System.ComponentModel.Composition.Hosting
10 public static class CompositionHost
12 // Field is internal only to assist in testing
13 internal static CompositionContainer _container = null;
14 private static object _lockObject = new object();
16 /// <summary>
17 /// This method can be used to initialize the global container used by <see cref="CompositionInitializer.SatisfyImports(object)"/>
18 /// in case where the default container doesn't provide enough flexibility.
19 ///
20 /// If this method is needed it should be called exactly once and as early as possible in the application host. It will need
21 /// to be called before the first call to <see cref="CompositionInitializer.SatisfyImports(object)"/>
22 /// </summary>
23 /// <param name="container">
24 /// <see cref="CompositionContainer"/> that should be used instead of the default global container.
25 /// </param>
26 /// <exception cref="ArgumentNullException">
27 /// <paramref name="container"/> is <see langword="null"/>.
28 /// </exception>
29 /// <exception cref="InvalidOperationException">
30 /// Either <see cref="Initialize(CompositionContainer)" /> or <see cref="Initialize(ComposablePartCatalog[])" /> has already been called or someone has already made use of the global
31 /// container via <see cref="CompositionInitializer.SatisfyImports(object)"/>. In either case you need to ensure that it
32 /// is called only once and that it is called early in the application host startup code.
33 /// </exception>
34 public static void Initialize(CompositionContainer container)
36 if (container == null)
38 throw new ArgumentNullException("container");
41 CompositionContainer globalContainer = null;
42 bool alreadyCreated = TryGetOrCreateContainer(() => container, out globalContainer);
44 if (alreadyCreated)
46 throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
47 Strings.InvalidOperationException_GlobalContainerAlreadyInitialized));
51 /// <summary>
52 /// This method can be used to initialize the global container used by <see cref="CompositionInitializer.SatisfyImports(object)"/>
53 /// in case where the default container doesn't provide enough flexibility.
54 ///
55 /// If this method is needed it should be called exactly once and as early as possible in the application host. It will need
56 /// to be called before the first call to <see cref="CompositionInitializer.SatisfyImports(object)"/>
57 /// </summary>
58 /// <param name="catalogs">
59 /// An array of <see cref="ComposablePartCatalog"/> that should be used to initialize the <see cref="CompositionContainer"/> with.
60 /// </param>
61 /// <exception cref="ArgumentNullException">
62 /// <paramref name="catalogs"/> is <see langword="null"/>.
63 /// </exception>
64 /// <exception cref="InvalidOperationException">
65 /// Either <see cref="Initialize(CompositionContainer)" /> or <see cref="Initialize(ComposablePartCatalog[])" />has already been called or someone has already made use of the global
66 /// container via <see cref="CompositionInitializer.SatisfyImports(object)"/>. In either case you need to ensure that it
67 /// is called only once and that it is called early in the application host startup code.
68 /// </exception>
69 public static CompositionContainer Initialize(params ComposablePartCatalog[] catalogs)
71 AggregateCatalog aggregateCatalog = new AggregateCatalog(catalogs);
72 CompositionContainer container = new CompositionContainer(aggregateCatalog);
73 try
75 CompositionHost.Initialize(container);
77 catch
79 container.Dispose();
81 // NOTE : this is important, as this prevents the disposal of the catalogs passed as input arguments
82 aggregateCatalog.Catalogs.Clear();
83 aggregateCatalog.Dispose();
85 throw;
88 return container;
93 internal static bool TryGetOrCreateContainer(Func<CompositionContainer> createContainer, out CompositionContainer globalContainer)
95 bool alreadyCreated = true;
96 if (_container == null)
98 var container = createContainer.Invoke();
99 lock (_lockObject)
101 if (_container == null)
103 Thread.MemoryBarrier();
104 _container = container;
105 alreadyCreated = false;
109 globalContainer = _container;
110 return alreadyCreated;