// ----------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. // ----------------------------------------------------------------------- using System; using System.ComponentModel.Composition.Factories; using System.ComponentModel.Composition.Hosting; using System.ComponentModel.Composition.Primitives; using System.Reflection; using Microsoft.Internal; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; using System.Linq; using System.UnitTesting; using System.Threading; namespace System.ComponentModel.Composition.ReflectionModel { [TestClass] public class ReflectionComposablePartDefinitionTests { private ReflectionComposablePartDefinition CreateReflectionPartDefinition( Lazy partType, bool requiresDisposal, Func> imports, Func>exports, IDictionary metadata, ICompositionElement origin) { return (ReflectionComposablePartDefinition)ReflectionModelServices.CreatePartDefinition(partType, requiresDisposal, new Lazy>(imports, false), new Lazy>(exports, false), metadata.AsLazy(), origin); } [TestMethod] public void Constructor() { Type expectedType = typeof(TestPart); Lazy expectedLazyType = expectedType.AsLazy(); IDictionary expectedMetadata = new Dictionary(); expectedMetadata["Key1"] = 1; expectedMetadata["Key2"] = "Value2"; IEnumerable expectedImports = CreateImports(expectedType); IEnumerable expectedExports = CreateExports(expectedType); ICompositionElement expectedOrigin = new MockOrigin(); ReflectionComposablePartDefinition definition = CreateReflectionPartDefinition( expectedLazyType, false, () => expectedImports, () => expectedExports, expectedMetadata, expectedOrigin); Assert.AreSame(expectedType, definition.GetPartType()); Assert.IsTrue(definition.Metadata.Keys.SequenceEqual(expectedMetadata.Keys)); Assert.IsTrue(definition.Metadata.Values.SequenceEqual(expectedMetadata.Values)); Assert.IsTrue(definition.ExportDefinitions.SequenceEqual(expectedExports.Cast())); Assert.IsTrue(definition.ImportDefinitions.SequenceEqual(expectedImports.Cast())); Assert.AreSame(expectedOrigin, ((ICompositionElement)definition).Origin); Assert.IsNotNull(((ICompositionElement)definition).DisplayName); Assert.IsFalse(definition.IsDisposalRequired); } [TestMethod] public void Constructor_DisposablePart() { Type expectedType = typeof(TestPart); Lazy expectedLazyType = expectedType.AsLazy(); IDictionary expectedMetadata = new Dictionary(); expectedMetadata["Key1"] = 1; expectedMetadata["Key2"] = "Value2"; IEnumerable expectedImports = CreateImports(expectedType); IEnumerable expectedExports = CreateExports(expectedType); ICompositionElement expectedOrigin = new MockOrigin(); ReflectionComposablePartDefinition definition = CreateReflectionPartDefinition( expectedLazyType, true, () => expectedImports, () => expectedExports, expectedMetadata, expectedOrigin); Assert.AreSame(expectedType, definition.GetPartType()); Assert.IsTrue(definition.Metadata.Keys.SequenceEqual(expectedMetadata.Keys)); Assert.IsTrue(definition.Metadata.Values.SequenceEqual(expectedMetadata.Values)); Assert.IsTrue(definition.ExportDefinitions.SequenceEqual(expectedExports.Cast())); Assert.IsTrue(definition.ImportDefinitions.SequenceEqual(expectedImports.Cast())); Assert.AreSame(expectedOrigin, ((ICompositionElement)definition).Origin); Assert.IsNotNull(((ICompositionElement)definition).DisplayName); Assert.IsTrue(definition.IsDisposalRequired); } [TestMethod] public void CreatePart() { Type expectedType = typeof(TestPart); Lazy expectedLazyType = expectedType.AsLazy(); IDictionary expectedMetadata = new Dictionary(); expectedMetadata["Key1"] = 1; expectedMetadata["Key2"] = "Value2"; IEnumerable expectedImports = CreateImports(expectedType); IEnumerable expectedExports = CreateExports(expectedType); ICompositionElement expectedOrigin = new MockOrigin(); ReflectionComposablePartDefinition definition = CreateReflectionPartDefinition( expectedLazyType, false, () => expectedImports, () => expectedExports, expectedMetadata, expectedOrigin); var part = definition.CreatePart(); Assert.IsNotNull(part); Assert.IsFalse(part is IDisposable); } [TestMethod] public void CreatePart_Disposable() { Type expectedType = typeof(TestPart); Lazy expectedLazyType = expectedType.AsLazy(); IDictionary expectedMetadata = new Dictionary(); expectedMetadata["Key1"] = 1; expectedMetadata["Key2"] = "Value2"; IEnumerable expectedImports = CreateImports(expectedType); IEnumerable expectedExports = CreateExports(expectedType); ICompositionElement expectedOrigin = new MockOrigin(); ReflectionComposablePartDefinition definition = CreateReflectionPartDefinition( expectedLazyType, true, () => expectedImports, () => expectedExports, expectedMetadata, expectedOrigin); var part = definition.CreatePart(); Assert.IsNotNull(part); Assert.IsTrue(part is IDisposable); } [TestMethod] public void CreatePart_DoesntLoadType() { Type expectedType = typeof(TestPart); Lazy expectedLazyType = new Lazy(() => { Assert.Fail("Part should not be loaded"); return null; }); IDictionary expectedMetadata = new Dictionary(); expectedMetadata["Key1"] = 1; expectedMetadata["Key2"] = "Value2"; IEnumerable expectedImports = CreateImports(expectedType); IEnumerable expectedExports = CreateExports(expectedType); ICompositionElement expectedOrigin = new MockOrigin(); ReflectionComposablePartDefinition definition = CreateReflectionPartDefinition( expectedLazyType, true, () => expectedImports, () => expectedExports, expectedMetadata, expectedOrigin); var part = definition.CreatePart(); Assert.IsNotNull(part); Assert.IsTrue(part is IDisposable); } [TestMethod] public void Constructor_NullMetadata_ShouldSetMetadataPropertyToEmpty() { ReflectionComposablePartDefinition definition = CreateEmptyDefinition(typeof(object), typeof(object).GetConstructors().First(), null, new MockOrigin()); Assert.IsNotNull(definition.Metadata); Assert.AreEqual(0, definition.Metadata.Count); } [TestMethod] public void Constructor_NullOrigin_ShouldSetOriginPropertyToNull() { ReflectionComposablePartDefinition definition = CreateEmptyDefinition(typeof(object), typeof(object).GetConstructors().First(), MetadataServices.EmptyMetadata, null); Assert.IsNotNull(((ICompositionElement)definition).DisplayName); Assert.IsNull(((ICompositionElement)definition).Origin); } [TestMethod] public void ImportaAndExports_CreatorsShouldBeCalledLazilyAndOnce() { Type expectedType = typeof(TestPart); IEnumerable expectedImports = CreateImports(expectedType); IEnumerable expectedExports = CreateExports(expectedType); bool importsCreatorCalled = false; Func> importsCreator = () => { Assert.IsFalse(importsCreatorCalled); importsCreatorCalled = true; return expectedImports.Cast(); }; bool exportsCreatorCalled = false; Func> exportsCreator = () => { Assert.IsFalse(exportsCreatorCalled); exportsCreatorCalled = true; return expectedExports.Cast(); }; ReflectionComposablePartDefinition definition = CreateReflectionPartDefinition( expectedType.AsLazy(), false, importsCreator, exportsCreator, null, null); IEnumerable exports; Assert.IsFalse(exportsCreatorCalled); exports = definition.ExportDefinitions; Assert.IsTrue(exportsCreatorCalled); exports = definition.ExportDefinitions; IEnumerable imports; Assert.IsFalse(importsCreatorCalled); imports = definition.ImportDefinitions; Assert.IsTrue(importsCreatorCalled); imports = definition.ImportDefinitions; } [TestMethod] public void ICompositionElementDisplayName_ShouldReturnTypeDisplayName() { var expectations = Expectations.GetAttributedTypes(); foreach (var e in expectations) { var definition = (ICompositionElement)CreateEmptyDefinition(e, null, null, null); Assert.AreEqual(e.GetDisplayName(), definition.DisplayName); } } [TestMethod] public void ToString_ShouldReturnICompositionElementDisplayName() { var expectations = Expectations.GetAttributedTypes(); foreach (var e in expectations) { var definition = (ICompositionElement)CreateEmptyDefinition(e, null, null, null); Assert.AreEqual(definition.DisplayName, definition.ToString()); } } private ReflectionComposablePartDefinition CreateEmptyDefinition(Type type, ConstructorInfo constructor, IDictionary metadata, ICompositionElement origin) { return (ReflectionComposablePartDefinition)ReflectionModelServices.CreatePartDefinition( (type != null) ? type.AsLazy() : null, false, Enumerable.Empty().AsLazy(), Enumerable.Empty().AsLazy(), metadata.AsLazy(), origin); } private static List CreateImports(Type type) { List imports = new List(); foreach (PropertyInfo property in type.GetProperties()) { imports.Add(new ReflectionMemberImportDefinition(new LazyMemberInfo(property), "Contract", (string)null, new KeyValuePair[] { new KeyValuePair("Key1", typeof(object)) }, ImportCardinality.ZeroOrOne, true, CreationPolicy.Any, new TypeOrigin(type))); } return imports; } private static List CreateExports(Type type) { List exports = new List(); foreach (PropertyInfo property in type.GetProperties()) { exports.Add(ReflectionModelServices.CreateExportDefinition(new LazyMemberInfo(property), "Contract", new Lazy>(() => null, false), new TypeOrigin(type))); } return exports; } public class TestPart { public int field1; public string field2; public int Property1 { get; set; } public string Property2 { get; set; } } private class TypeOrigin : ICompositionElement { private readonly Type _type; private readonly ICompositionElement _orgin; public TypeOrigin(Type type) : this(type, null) { } public TypeOrigin(Type type, ICompositionElement origin) { this._type = type; this._orgin = origin; } public string DisplayName { get { return this._type.GetDisplayName(); } } public ICompositionElement Origin { get { return this._orgin; } } } private class MockOrigin : ICompositionElement { public string DisplayName { get { throw new NotImplementedException(); } } public ICompositionElement Origin { get { throw new NotImplementedException(); } } } } }