1 // -----------------------------------------------------------------------
\r
2 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
3 // -----------------------------------------------------------------------
\r
5 using System.Collections.Generic;
\r
6 using System.ComponentModel.Composition;
\r
7 using Microsoft.VisualStudio.TestTools.UnitTesting;
\r
8 using System.ComponentModel.Composition.Factories;
\r
9 using System.ComponentModel.Composition.UnitTesting;
\r
10 using System.UnitTesting;
\r
11 using System.ComponentModel.Composition.AttributedModel;
\r
12 using System.ComponentModel.Composition.Hosting;
\r
13 using System.ComponentModel.Composition.Primitives;
\r
15 using System.ComponentModel.Composition.ReflectionModel;
\r
16 using Microsoft.Internal;
\r
18 namespace Tests.Integration
\r
21 public class DelayLoadingTests
\r
24 public void PartTypeLoadedLazily()
\r
26 var catalog = new TypeLoadNotifyingCatalog(typeof(ExportingPart));
\r
27 var container = new CompositionContainer(catalog);
\r
28 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
29 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
31 Lazy<IExporter> lazyContract = container.GetExport<IExporter>();
\r
32 Assert.IsNotNull(lazyContract);
\r
33 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
34 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
36 IExporter value = lazyContract.Value;
\r
38 catalog.AssertLoaded(typeof(ExportingPart));
\r
39 Assert.AreEqual(1, catalog.LoadedTypes.Count());
\r
43 public void PartTypeLoadedLazilyEagerDependeciesLoadEagerly()
\r
45 var catalog = new TypeLoadNotifyingCatalog(typeof(ExportingPart), typeof(PartImportingEagerly));
\r
46 var container = new CompositionContainer(catalog);
\r
47 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
48 catalog.AssertNotLoaded(typeof(PartImportingEagerly));
\r
49 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
51 Lazy<IImporter> lazyContract = container.GetExport<IImporter>();
\r
52 Assert.IsNotNull(lazyContract);
\r
53 catalog.AssertNotLoaded(typeof(PartImportingEagerly));
\r
54 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
55 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
57 IImporter value = lazyContract.Value;
\r
58 catalog.AssertLoaded(typeof(PartImportingEagerly));
\r
59 catalog.AssertLoaded(typeof(ExportingPart));
\r
60 Assert.AreEqual(2, catalog.LoadedTypes.Count());
\r
64 public void PartTypeLoadedLazilyLazyDependeciesLoadLazily()
\r
66 var catalog = new TypeLoadNotifyingCatalog(typeof(ExportingPart), typeof(PartImportingLazily));
\r
67 var container = new CompositionContainer(catalog);
\r
68 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
69 catalog.AssertNotLoaded(typeof(PartImportingLazily));
\r
70 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
72 Lazy<IImporter> lazyContract = container.GetExport<IImporter>();
\r
73 Assert.IsNotNull(lazyContract);
\r
74 catalog.AssertNotLoaded(typeof(PartImportingLazily));
\r
75 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
76 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
78 IImporter value = lazyContract.Value;
\r
79 catalog.AssertLoaded(typeof(PartImportingLazily));
\r
80 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
81 Assert.AreEqual(1, catalog.LoadedTypes.Count());
\r
85 public void PartTypeLoadedLazilyEagerCollectionDependeciesLoadEagerly()
\r
87 var catalog = new TypeLoadNotifyingCatalog(typeof(ExportingPart), typeof(PartImportingCollectionEagerly));
\r
88 var container = new CompositionContainer(catalog);
\r
89 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
90 catalog.AssertNotLoaded(typeof(PartImportingCollectionEagerly));
\r
91 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
93 Lazy<IImporter> lazyContract = container.GetExport<IImporter>();
\r
94 Assert.IsNotNull(lazyContract);
\r
95 catalog.AssertNotLoaded(typeof(PartImportingCollectionEagerly));
\r
96 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
97 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
99 IImporter value = lazyContract.Value;
\r
100 catalog.AssertLoaded(typeof(PartImportingCollectionEagerly));
\r
101 catalog.AssertLoaded(typeof(ExportingPart));
\r
102 Assert.AreEqual(2, catalog.LoadedTypes.Count());
\r
106 public void PartTypeLoadedLazilyLazyCollectionDependeciesLoadLazily()
\r
108 var catalog = new TypeLoadNotifyingCatalog(typeof(ExportingPart), typeof(PartImportingCollectionLazily));
\r
109 var container = new CompositionContainer(catalog);
\r
110 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
111 catalog.AssertNotLoaded(typeof(PartImportingCollectionLazily));
\r
112 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
114 Lazy<IImporter> lazyContract = container.GetExport<IImporter>();
\r
115 Assert.IsNotNull(lazyContract);
\r
116 catalog.AssertNotLoaded(typeof(PartImportingCollectionLazily));
\r
117 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
118 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
120 IImporter value = lazyContract.Value;
\r
121 catalog.AssertLoaded(typeof(PartImportingCollectionLazily));
\r
122 catalog.AssertNotLoaded(typeof(ExportingPart));
\r
123 Assert.AreEqual(1, catalog.LoadedTypes.Count());
\r
128 public void PartTypeLoadedLazilyLazyLoopLoadsLazily()
\r
130 var catalog = new TypeLoadNotifyingCatalog(typeof(LazyLoopImporter), typeof(LazyLoopExporter));
\r
131 var container = new CompositionContainer(catalog);
\r
132 catalog.AssertNotLoaded(typeof(LazyLoopImporter));
\r
133 catalog.AssertNotLoaded(typeof(LazyLoopExporter));
\r
134 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
136 Lazy<IImporter> lazyContract = container.GetExport<IImporter>();
\r
137 Assert.IsNotNull(lazyContract);
\r
138 catalog.AssertNotLoaded(typeof(LazyLoopImporter));
\r
139 catalog.AssertNotLoaded(typeof(LazyLoopExporter));
\r
140 Assert.AreEqual(0, catalog.LoadedTypes.Count());
\r
142 IImporter value = lazyContract.Value;
\r
143 catalog.AssertLoaded(typeof(LazyLoopImporter));
\r
144 catalog.AssertNotLoaded(typeof(LazyLoopExporter));
\r
145 Assert.AreEqual(1, catalog.LoadedTypes.Count());
\r
148 public class IExporter
\r
152 public class IImporter
\r
156 [Export(typeof(IExporter))]
\r
157 public class ExportingPart : IExporter
\r
161 [Export(typeof(IImporter))]
\r
162 public class PartImportingLazily : IImporter
\r
165 public Lazy<IExporter> Exporter { get; set; }
\r
168 [Export(typeof(IImporter))]
\r
169 public class PartImportingCollectionLazily : IImporter
\r
172 public IEnumerable<Lazy<IExporter>> Exporters { get; set; }
\r
175 [Export(typeof(IImporter))]
\r
176 public class PartImportingEagerly : IImporter
\r
179 public IExporter Exporter { get; set; }
\r
182 [Export(typeof(IImporter))]
\r
183 public class PartImportingCollectionEagerly : IImporter
\r
186 public IEnumerable<IExporter> Exporters { get; set; }
\r
190 [Export(typeof(IImporter))]
\r
191 public class LazyLoopImporter : IImporter
\r
194 public Lazy<IExporter> Exporter { get; set; }
\r
197 [Export(typeof(IExporter))]
\r
198 public class LazyLoopExporter : IExporter
\r
201 public Lazy<IImporter> Importer { get; set; }
\r
205 private class TypeLoadNotifyingCatalog : ComposablePartCatalog
\r
207 ComposablePartDefinition[] _definitions;
\r
208 public HashSet<Type> LoadedTypes { get; private set; }
\r
210 public TypeLoadNotifyingCatalog(params Type[] types)
\r
212 this._definitions = types.Select(type => this.CreatePartDefinition(type)).ToArray();
\r
213 this.LoadedTypes = new HashSet<Type>();
\r
216 public override IQueryable<ComposablePartDefinition> Parts
\r
218 get { return this._definitions.AsQueryable(); }
\r
221 private ComposablePartDefinition CreatePartDefinition(Type type)
\r
223 ComposablePartDefinition partDefinition = AttributedModelServices.CreatePartDefinition(type, null);
\r
224 return this.CreateWrapped(partDefinition, type);
\r
227 private ComposablePartDefinition CreateWrapped(ComposablePartDefinition partDefinition, Type type)
\r
229 IEnumerable<ExportDefinition> exports = partDefinition.ExportDefinitions.Select(e => this.CreateWrapped(e, type)).ToArray();
\r
230 IEnumerable<ImportDefinition> imports = partDefinition.ImportDefinitions.Cast<ContractBasedImportDefinition>().Select(i => this.CreateWrapped(i, type)).ToArray();
\r
232 return ReflectionModelServices.CreatePartDefinition(
\r
233 this.CreateWrapped(ReflectionModelServices.GetPartType(partDefinition), type),
\r
234 ReflectionModelServices.IsDisposalRequired(partDefinition),
\r
237 partDefinition.Metadata.AsLazy(),
\r
241 private Lazy<T> CreateWrapped<T>(Lazy<T> lazy, Type type)
\r
243 return new Lazy<T>(
\r
244 () => { this.OnTypeLoaded(type); return lazy.Value; });
\r
247 private LazyMemberInfo CreateWrapped(LazyMemberInfo lazyMember, Type type)
\r
249 return new LazyMemberInfo(
\r
250 lazyMember.MemberType,
\r
251 () => { this.OnTypeLoaded(type); return lazyMember.GetAccessors(); });
\r
254 private ExportDefinition CreateWrapped(ExportDefinition export, Type type)
\r
256 return ReflectionModelServices.CreateExportDefinition(
\r
257 this.CreateWrapped(ReflectionModelServices.GetExportingMember(export), type),
\r
258 export.ContractName,
\r
259 export.Metadata.AsLazy(),
\r
263 private ImportDefinition CreateWrapped(ContractBasedImportDefinition import, Type type)
\r
265 if (ReflectionModelServices.IsImportingParameter(import))
\r
267 return ReflectionModelServices.CreateImportDefinition(
\r
268 this.CreateWrapped(ReflectionModelServices.GetImportingParameter(import), type),
\r
269 import.ContractName,
\r
270 import.RequiredTypeIdentity,
\r
271 import.RequiredMetadata,
\r
272 import.Cardinality,
\r
273 import.RequiredCreationPolicy,
\r
278 return ReflectionModelServices.CreateImportDefinition(
\r
279 this.CreateWrapped(ReflectionModelServices.GetImportingMember(import), type),
\r
280 import.ContractName,
\r
281 import.RequiredTypeIdentity,
\r
282 import.RequiredMetadata,
\r
283 import.Cardinality,
\r
284 import.IsRecomposable,
\r
285 import.RequiredCreationPolicy,
\r
292 private void OnTypeLoaded(Type type)
\r
294 this.LoadedTypes.Add(type);
\r
297 public void AssertLoaded(Type type)
\r
299 Assert.IsTrue(this.LoadedTypes.Contains(type));
\r
302 public void AssertNotLoaded(Type type)
\r
304 Assert.IsFalse(this.LoadedTypes.Contains(type));
\r