1
// -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
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();
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.
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)"/>
23 /// <param name="container">
24 /// <see cref="CompositionContainer"/> that should be used instead of the default global container.
26 /// <exception cref="ArgumentNullException">
27 /// <paramref name="container"/> is <see langword="null"/>.
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.
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
);
46 throw new InvalidOperationException(String
.Format(CultureInfo
.CurrentCulture
,
47 Strings
.InvalidOperationException_GlobalContainerAlreadyInitialized
));
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.
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)"/>
58 /// <param name="catalogs">
59 /// An array of <see cref="ComposablePartCatalog"/> that should be used to initialize the <see cref="CompositionContainer"/> with.
61 /// <exception cref="ArgumentNullException">
62 /// <paramref name="catalogs"/> is <see langword="null"/>.
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.
69 public static CompositionContainer
Initialize(params ComposablePartCatalog
[] catalogs
)
71 AggregateCatalog aggregateCatalog
= new AggregateCatalog(catalogs
);
72 CompositionContainer container
= new CompositionContainer(aggregateCatalog
);
75 CompositionHost
.Initialize(container
);
81 // NOTE : this is important, as this prevents the disposal of the catalogs passed as input arguments
82 aggregateCatalog
.Catalogs
.Clear();
83 aggregateCatalog
.Dispose();
93 internal static bool TryGetOrCreateContainer(Func
<CompositionContainer
> createContainer
, out CompositionContainer globalContainer
)
95 bool alreadyCreated
= true;
96 if (_container
== null)
98 var container
= createContainer
.Invoke();
101 if (_container
== null)
103 Thread
.MemoryBarrier();
104 _container
= container
;
105 alreadyCreated
= false;
109 globalContainer
= _container
;
110 return alreadyCreated
;