DiscoveryTests.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. // -----------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. // -----------------------------------------------------------------------
  4. using System;
  5. using System.Collections.Generic;
  6. using System.ComponentModel.Composition;
  7. using System.ComponentModel.Composition.AttributedModel;
  8. using System.ComponentModel.Composition.Primitives;
  9. using System.ComponentModel.Composition.Factories;
  10. using System.ComponentModel.Composition.Hosting;
  11. using System.ComponentModel.Composition.UnitTesting;
  12. using System.Linq;
  13. using System.Reflection;
  14. using System.UnitTesting;
  15. using Microsoft.VisualStudio.TestTools.UnitTesting;
  16. namespace Tests.Integration
  17. {
  18. [TestClass]
  19. public class DiscoveryTests
  20. {
  21. public abstract class AbstractClassWithExports
  22. {
  23. [Export("StaticExport")]
  24. public static string StaticExport { get { return "ExportedValue"; } }
  25. [Export("InstanceExport")]
  26. public string InstanceExport { get { return "InstanceExportedValue"; } }
  27. }
  28. [TestMethod]
  29. public void Export_StaticOnAbstractClass_ShouldExist()
  30. {
  31. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(AbstractClassWithExports));
  32. Assert.IsTrue(container.IsPresent("StaticExport"));
  33. Assert.IsFalse(container.IsPresent("InstanceExport"));
  34. }
  35. public class ClassWithStaticImport
  36. {
  37. [Import("StaticImport")]
  38. public static string MyImport
  39. {
  40. get; set;
  41. }
  42. }
  43. [TestMethod]
  44. public void Import_StaticImport_ShouldNotBeSet()
  45. {
  46. var container = ContainerFactory.Create();
  47. container.AddAndComposeExportedValue("StaticImport", "String that shouldn't be imported");
  48. var importer = new ClassWithStaticImport();
  49. container.SatisfyImportsOnce(importer);
  50. Assert.IsNull(ClassWithStaticImport.MyImport, "Static import should not have been set!");
  51. }
  52. #if !SILVERLIGHT
  53. // private imports don't work on SILVERLIGHT
  54. [Export]
  55. public class BaseWithNonPublicImportAndExport
  56. {
  57. [Import("BasePrivateImport")]
  58. private string _basePrivateImport = null;
  59. public string BasePrivateImport { get { return this._basePrivateImport; } }
  60. }
  61. [Export]
  62. public class DerivedBaseWithNonPublicImportAndExport : BaseWithNonPublicImportAndExport
  63. {
  64. }
  65. [TestMethod]
  66. public void Import_PrivateOnClass_ShouldSetImport()
  67. {
  68. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(BaseWithNonPublicImportAndExport));
  69. container.AddAndComposeExportedValue("BasePrivateImport", "Imported String");
  70. var importer = container.GetExportedValue<BaseWithNonPublicImportAndExport>();
  71. Assert.AreEqual("Imported String", importer.BasePrivateImport);
  72. }
  73. [TestMethod]
  74. public void Import_PrivateOnBase_ShouldSetImport()
  75. {
  76. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(DerivedBaseWithNonPublicImportAndExport));
  77. container.AddAndComposeExportedValue("BasePrivateImport", "Imported String");
  78. var importer = container.GetExportedValue<DerivedBaseWithNonPublicImportAndExport>();
  79. Assert.AreEqual("Imported String", importer.BasePrivateImport);
  80. }
  81. #endif // !SILVERLIGHT
  82. public interface InterfaceWithImport
  83. {
  84. [Import("InterfaceImport")]
  85. int MyImport { get; set; }
  86. }
  87. public interface InterfaceWithExport
  88. {
  89. [Export("InterfaceExport")]
  90. int MyExport { get; set; }
  91. }
  92. [TestMethod]
  93. public void AttributesOnInterface_ShouldNotBeConsiderAPart()
  94. {
  95. var catalog = CatalogFactory.CreateAttributed(
  96. typeof(InterfaceWithImport),
  97. typeof(InterfaceWithExport));
  98. Assert.AreEqual(0, catalog.Parts.Count());
  99. }
  100. [Export]
  101. public class ClassWithInterfaceInheritedImport : InterfaceWithImport
  102. {
  103. public int MyImport { get; set; }
  104. }
  105. [TestMethod]
  106. public void Import_InheritImportFromInterface_ShouldExposeImport()
  107. {
  108. var container = ContainerFactory.CreateWithAttributedCatalog(
  109. typeof(ClassWithInterfaceInheritedImport));
  110. container.AddAndComposeExportedValue("InterfaceImport", 42);
  111. var importer = container.GetExportedValue<ClassWithInterfaceInheritedImport>();
  112. Assert.IsTrue(importer.MyImport == default(int), "Imports declared on interfaces should not be discovered");
  113. }
  114. public class ClassWithInterfaceInheritedExport : InterfaceWithExport
  115. {
  116. public ClassWithInterfaceInheritedExport()
  117. {
  118. MyExport = 42;
  119. }
  120. public int MyExport { get; set; }
  121. }
  122. [TestMethod]
  123. public void Import_InheritExportFromInterface_ShouldNotExposeExport()
  124. {
  125. var container = ContainerFactory.CreateWithAttributedCatalog(
  126. typeof(ClassWithInterfaceInheritedExport));
  127. Assert.IsFalse(container.IsPresent("InterfaceExport"), "Export defined on interface should not be discovered!");
  128. }
  129. public interface IFoo { }
  130. [InheritedExport]
  131. public abstract class BaseWithVirtualExport
  132. {
  133. [Export]
  134. public virtual IFoo MyProp { get; set; }
  135. }
  136. [InheritedExport(typeof(BaseWithVirtualExport))]
  137. public class DerivedWithOverrideExport : BaseWithVirtualExport
  138. {
  139. [Export]
  140. public override IFoo MyProp { get; set; }
  141. }
  142. [TestMethod]
  143. public void Export_BaseAndDerivedShouldAmountInTwoExports()
  144. {
  145. var container = ContainerFactory.CreateWithAttributedCatalog(
  146. typeof(BaseWithVirtualExport),
  147. typeof(DerivedWithOverrideExport));
  148. var exports1 = container.GetExportedValues<BaseWithVirtualExport>();
  149. Assert.AreEqual(1, exports1.Count());
  150. var exports2 = container.GetExportedValues<IFoo>();
  151. Assert.AreEqual(1, exports2.Count());
  152. }
  153. public interface IDocument { }
  154. [Export(typeof(IDocument))]
  155. [ExportMetadata("Name", "TextDocument")]
  156. public class TextDocument : IDocument
  157. {
  158. }
  159. [Export(typeof(IDocument))]
  160. [ExportMetadata("Name", "XmlDocument")]
  161. public class XmlDocument : TextDocument
  162. {
  163. }
  164. [TestMethod]
  165. public void Export_ExportingSameContractInDerived_ShouldResultInHidingBaseExport()
  166. {
  167. var container = ContainerFactory.CreateWithAttributedCatalog(
  168. typeof(IDocument),
  169. typeof(XmlDocument));
  170. var export = container.GetExport<IDocument, IDictionary<string, object>>();
  171. Assert.AreEqual("XmlDocument", export.Metadata["Name"]);
  172. }
  173. [TestMethod]
  174. public void Export_ExportingBaseAndDerivedSameContract_ShouldResultInOnlyTwoExports()
  175. {
  176. var container = ContainerFactory.CreateWithAttributedCatalog(
  177. typeof(IDocument),
  178. typeof(TextDocument),
  179. typeof(XmlDocument));
  180. var exports = container.GetExports<IDocument, IDictionary<string, object>>();
  181. Assert.AreEqual(2, exports.Count());
  182. Assert.AreEqual("TextDocument", exports.ElementAt(0).Metadata["Name"]);
  183. Assert.IsInstanceOfType(exports.ElementAt(0).Value, typeof(TextDocument));
  184. Assert.AreEqual("XmlDocument", exports.ElementAt(1).Metadata["Name"]);
  185. Assert.IsInstanceOfType(exports.ElementAt(1).Value, typeof(XmlDocument));
  186. }
  187. public interface IObjectSerializer { }
  188. [Export(typeof(IDocument))]
  189. [Export(typeof(IObjectSerializer))]
  190. [ExportMetadata("Name", "XamlDocument")]
  191. public class XamlDocument : XmlDocument, IObjectSerializer
  192. {
  193. }
  194. [TestMethod]
  195. public void Export_ExportingSameContractInDerivedAndNewContract_ShouldResultInHidingBaseAndExportingNewContract()
  196. {
  197. var container = ContainerFactory.CreateWithAttributedCatalog(
  198. typeof(XamlDocument));
  199. var export = container.GetExport<IDocument, IDictionary<string, object>>();
  200. Assert.AreEqual("XamlDocument", export.Metadata["Name"]);
  201. var export2 = container.GetExport<IObjectSerializer, IDictionary<string, object>>();
  202. Assert.AreEqual("XamlDocument", export2.Metadata["Name"]);
  203. }
  204. [Export(typeof(IDocument))]
  205. [ExportMetadata("Name", "WPFDocument")]
  206. public class WPFDocument : XamlDocument
  207. {
  208. }
  209. [TestMethod]
  210. public void Export_ExportingSameContractInDerivedAndAnotherContractInBase_ShouldResultInHidingOneBaseAndInheritingNewContract()
  211. {
  212. var container = ContainerFactory.CreateWithAttributedCatalog(
  213. typeof(WPFDocument));
  214. var export = container.GetExport<IDocument, IDictionary<string, object>>();
  215. Assert.AreEqual("WPFDocument", export.Metadata["Name"]);
  216. var export2 = container.GetExportedValueOrDefault<IObjectSerializer>();
  217. Assert.IsNull(export2, "IObjectSerializer export should not have been inherited");
  218. }
  219. [InheritedExport]
  220. public abstract class Plugin
  221. {
  222. public virtual string GetLocation()
  223. {
  224. return "NoWhere";
  225. }
  226. public virtual int Version
  227. {
  228. get
  229. {
  230. return 0;
  231. }
  232. }
  233. }
  234. private void VerifyValidPlugin(CompositionContainer container, int version, string location)
  235. {
  236. var plugins = container.GetExports<Plugin>();
  237. Assert.AreEqual(1, plugins.Count());
  238. var plugin = plugins.Single().Value;
  239. Assert.AreEqual(location, plugin.GetLocation());
  240. Assert.AreEqual(version, plugin.Version);
  241. }
  242. public class Plugin1 : Plugin
  243. {
  244. }
  245. [TestMethod]
  246. public void Export_Plugin1()
  247. {
  248. var container = ContainerFactory.CreateWithAttributedCatalog(
  249. typeof(Plugin1));
  250. VerifyValidPlugin(container, 0, "NoWhere");
  251. }
  252. public class Plugin2 : Plugin
  253. {
  254. public override string GetLocation()
  255. {
  256. return "SomeWhere";
  257. }
  258. public override int Version
  259. {
  260. get
  261. {
  262. return 1;
  263. }
  264. }
  265. }
  266. [TestMethod]
  267. public void Export_Plugin2()
  268. {
  269. var container = ContainerFactory.CreateWithAttributedCatalog(
  270. typeof(Plugin2));
  271. VerifyValidPlugin(container, 1, "SomeWhere");
  272. }
  273. public class Plugin3 : Plugin
  274. {
  275. [Export("PluginLocation")]
  276. public override string GetLocation()
  277. {
  278. return "SomeWhere3";
  279. }
  280. [Export("PluginVersion")]
  281. public override int Version
  282. {
  283. get
  284. {
  285. return 3;
  286. }
  287. }
  288. }
  289. [TestMethod]
  290. public void Export_Plugin3()
  291. {
  292. var container = ContainerFactory.CreateWithAttributedCatalog(
  293. typeof(Plugin3));
  294. VerifyValidPlugin(container, 3, "SomeWhere3");
  295. var plVer = container.GetExportedValue<int>("PluginVersion");
  296. Assert.AreEqual(3, plVer);
  297. var plLoc = container.GetExportedValue<Func<string>>("PluginLocation");
  298. Assert.AreEqual("SomeWhere3", plLoc());
  299. }
  300. [InheritedExport(typeof(Plugin))]
  301. public class Plugin4 : Plugin
  302. {
  303. public override string GetLocation()
  304. {
  305. return "SomeWhere4";
  306. }
  307. public override int Version
  308. {
  309. get
  310. {
  311. return 4;
  312. }
  313. }
  314. }
  315. [TestMethod]
  316. public void Export_Plugin4()
  317. {
  318. var container = ContainerFactory.CreateWithAttributedCatalog(
  319. typeof(Plugin4));
  320. VerifyValidPlugin(container, 4, "SomeWhere4");
  321. }
  322. public interface IPlugin
  323. {
  324. int Id { get; }
  325. }
  326. public class MyPlugin : IPlugin
  327. {
  328. [Export("PluginId")]
  329. public int Id { get { return 0; } }
  330. }
  331. [TestMethod]
  332. public void Export_MyPlugin()
  333. {
  334. var container = ContainerFactory.CreateWithAttributedCatalog(
  335. typeof(MyPlugin));
  336. var export = container.GetExportedValue<int>("PluginId");
  337. }
  338. [InheritedExport]
  339. public interface IApplicationPlugin
  340. {
  341. string Name { get; }
  342. object Application { get; set; }
  343. }
  344. [InheritedExport]
  345. public interface IToolbarPlugin : IApplicationPlugin
  346. {
  347. object ToolBar { get; set; }
  348. }
  349. public class MyToolbarPlugin : IToolbarPlugin
  350. {
  351. [Export("ApplicationPluginNames")]
  352. public string Name { get { return "MyToolbarPlugin"; } }
  353. [Import("Application")]
  354. public object Application { get; set; }
  355. [Import("ToolBar")]
  356. public object ToolBar { get; set; }
  357. }
  358. [TestMethod]
  359. public void TestInterfaces()
  360. {
  361. var container = ContainerFactory.CreateWithAttributedCatalog(
  362. typeof(MyToolbarPlugin));
  363. var app = new object();
  364. container.AddAndComposeExportedValue<object>("Application", app);
  365. var toolbar = new object();
  366. container.AddAndComposeExportedValue<object>("ToolBar", toolbar);
  367. var export = container.GetExportedValue<IToolbarPlugin>();
  368. Assert.AreEqual(app, export.Application);
  369. Assert.AreEqual(toolbar, export.ToolBar);
  370. Assert.AreEqual("MyToolbarPlugin", export.Name);
  371. var pluginNames = container.GetExportedValues<string>("ApplicationPluginNames");
  372. Assert.AreEqual(1, pluginNames.Count());
  373. }
  374. public class ImportOnVirtualProperty
  375. {
  376. public int ImportSetCount = 0;
  377. private int _value;
  378. [Import("VirtualImport")]
  379. public virtual int VirtualImport
  380. {
  381. get
  382. {
  383. return this._value;
  384. }
  385. set
  386. {
  387. this._value = value;
  388. ImportSetCount++;
  389. }
  390. }
  391. }
  392. public class ImportOnOverridenPropertyWithSameContract : ImportOnVirtualProperty
  393. {
  394. [Import("VirtualImport")]
  395. public override int VirtualImport
  396. {
  397. get
  398. {
  399. return base.VirtualImport;
  400. }
  401. set
  402. {
  403. base.VirtualImport = value;
  404. }
  405. }
  406. }
  407. [TestMethod]
  408. public void Import_VirtualPropertyOverrideWithSameContract_ShouldSucceed()
  409. {
  410. var container = ContainerFactory.Create();
  411. container.AddAndComposeExportedValue<int>("VirtualImport", 21);
  412. var import = new ImportOnOverridenPropertyWithSameContract();
  413. container.SatisfyImportsOnce(import);
  414. // Import will get set twice because there are 2 imports on the same property.
  415. // We would really like to either elminate it getting set twice or error in this case
  416. // but we figure it is a rare enough corner case that it doesn't warrented the run time cost
  417. // and can be covered by an FxCop rule.
  418. Assert.AreEqual(2, import.ImportSetCount);
  419. Assert.AreEqual(21, import.VirtualImport);
  420. }
  421. public class ImportOnOverridenPropertyWithDifferentContract : ImportOnVirtualProperty
  422. {
  423. [Import("OverriddenImport")]
  424. public override int VirtualImport
  425. {
  426. set
  427. {
  428. base.VirtualImport = value;
  429. }
  430. }
  431. }
  432. [TestMethod]
  433. public void Import_VirtualPropertyOverrideWithDifferentContract_ShouldSucceed()
  434. {
  435. var container = ContainerFactory.Create();
  436. container.AddAndComposeExportedValue<int>("VirtualImport", 21);
  437. container.AddAndComposeExportedValue<int>("OverriddenImport", 42);
  438. var import = new ImportOnOverridenPropertyWithSameContract();
  439. container.SatisfyImportsOnce(import);
  440. // Import will get set twice because there are 2 imports on the same property.
  441. // We would really like to either elminate it getting set twice or error in this case
  442. // but we figure it is a rare enough corner case that it doesn't warrented the run time cost
  443. // and can be covered by an FxCop rule.
  444. Assert.AreEqual(2, import.ImportSetCount);
  445. // The derived most import should be discovered first and so it will get set first
  446. // and thus the value should be the base import which is 21.
  447. Assert.AreEqual(21, import.VirtualImport);
  448. }
  449. [InheritedExport]
  450. public interface IOrderScreen { }
  451. public class NorthwindOrderScreen : IOrderScreen
  452. {
  453. }
  454. public class SouthsandOrderScreen : IOrderScreen
  455. {
  456. }
  457. [TestMethod]
  458. public void Export_ExportOnlyOnBaseInterfacewithInheritedMarked_ShouldFindAllImplementers()
  459. {
  460. var container = ContainerFactory.CreateWithAttributedCatalog(
  461. typeof(NorthwindOrderScreen),
  462. typeof(SouthsandOrderScreen));
  463. var exports = container.GetExportedValues<IOrderScreen>();
  464. Assert.AreEqual(2, exports.Count());
  465. Assert.IsInstanceOfType(exports.ElementAt(0), typeof(NorthwindOrderScreen));
  466. Assert.IsInstanceOfType(exports.ElementAt(1), typeof(SouthsandOrderScreen));
  467. }
  468. [Export]
  469. public class PartWithStaticConstructor
  470. {
  471. static PartWithStaticConstructor()
  472. {
  473. throw new Exception();
  474. }
  475. }
  476. [TestMethod]
  477. public void StaticConstructor()
  478. {
  479. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(PartWithStaticConstructor));
  480. CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotGetExportedValue,
  481. ErrorId.ImportEngine_PartCannotActivate,
  482. ErrorId.ReflectionModel_PartConstructorThrewException,
  483. () => container.GetExportedValue<PartWithStaticConstructor>());
  484. }
  485. public interface IAddin
  486. {
  487. void LoadAddin(object application);
  488. void Shutdown();
  489. }
  490. public interface IAddinMetadata
  491. {
  492. string Name { get; }
  493. string Version { get; }
  494. string Id { get; }
  495. }
  496. [MetadataAttribute]
  497. [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
  498. public class AddinAttribute : ExportAttribute, IAddinMetadata
  499. {
  500. private string _name;
  501. private string _version;
  502. private string _id;
  503. public AddinAttribute(string name, string version, string id)
  504. : base(typeof(IAddin))
  505. {
  506. this._name = name;
  507. this._version = version;
  508. this._id = id;
  509. }
  510. public string Name { get { return this._name; } }
  511. public string Version { get { return this._version; } }
  512. public string Id { get { return this._id; } }
  513. }
  514. [Addin("Addin1", "1.0", "{63D1B00F-AD2F-4F14-8A36-FFA59E4A101C}")]
  515. public class Addin1 : IAddin
  516. {
  517. public void LoadAddin(object application)
  518. {
  519. }
  520. public void Shutdown()
  521. {
  522. }
  523. }
  524. [Addin("Addin2", "1.0", "{63D1B00F-AD2F-4F14-8A36-FFA59E4A101D}")]
  525. public class Addin2 : IAddin
  526. {
  527. public void LoadAddin(object application)
  528. {
  529. }
  530. public void Shutdown()
  531. {
  532. }
  533. }
  534. [Addin("Addin3", "1.0", "{63D1B00F-AD2F-4F14-8A36-FFA59E4A101E}")]
  535. public class Addin3 : IAddin
  536. {
  537. public void LoadAddin(object application)
  538. {
  539. }
  540. public void Shutdown()
  541. {
  542. }
  543. }
  544. [TestMethod]
  545. public void DiscoverAddinsWithCombinedCustomExportAndMetadataAttribute()
  546. {
  547. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(Addin1), typeof(Addin2), typeof(Addin3));
  548. var addins = container.GetExports<IAddin, IAddinMetadata>().ToArray();
  549. Assert.AreEqual(3, addins.Length, "Incorrect number of addins");
  550. var values = new AddinAttribute[]
  551. {
  552. new AddinAttribute("Addin1", "1.0", "{63D1B00F-AD2F-4F14-8A36-FFA59E4A101C}"),
  553. new AddinAttribute("Addin2", "1.0", "{63D1B00F-AD2F-4F14-8A36-FFA59E4A101D}"),
  554. new AddinAttribute("Addin3", "1.0", "{63D1B00F-AD2F-4F14-8A36-FFA59E4A101E}"),
  555. };
  556. for (int i = 0; i < values.Length; i++)
  557. {
  558. var addinMetadata = addins[i].Metadata;
  559. Assert.AreEqual(values[i].Name, addinMetadata.Name);
  560. Assert.AreEqual(values[i].Version, addinMetadata.Version);
  561. Assert.AreEqual(values[i].Id, addinMetadata.Id);
  562. }
  563. }
  564. [TestMethod]
  565. public void CombinedCustomExportMetadataAttribute_ShouldNotContainMetadataFromExportAttribute()
  566. {
  567. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(Addin1));
  568. var addin = container.GetExport<IAddin, IDictionary<string, object>>();
  569. Assert.AreEqual(4, addin.Metadata.Count); // 3 metadata values and type identity
  570. Assert.AreEqual(AttributedModelServices.GetTypeIdentity(typeof(IAddin)), addin.Metadata[CompositionConstants.ExportTypeIdentityMetadataName]);
  571. Assert.AreEqual("Addin1", addin.Metadata["Name"]);
  572. Assert.AreEqual("1.0", addin.Metadata["Version"]);
  573. Assert.AreEqual("{63D1B00F-AD2F-4F14-8A36-FFA59E4A101C}", addin.Metadata["Id"]);
  574. }
  575. public class CustomInheritedExportAttribute : InheritedExportAttribute
  576. {
  577. }
  578. [CustomInheritedExport]
  579. public interface IUsesCustomInheritedExport
  580. {
  581. int Property { get; }
  582. }
  583. public class UsesCustomInheritedExportOnInterface : IUsesCustomInheritedExport
  584. {
  585. public int Property
  586. {
  587. get { return 42; }
  588. }
  589. }
  590. [TestMethod]
  591. public void Test_CustomInheritedExportAttribute_OnInterface()
  592. {
  593. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(UsesCustomInheritedExportOnInterface));
  594. var exporter = container.GetExportedValue<IUsesCustomInheritedExport>();
  595. Assert.AreEqual(42, exporter.Property);
  596. }
  597. [CustomInheritedExport]
  598. public class BaseClassWithCustomInheritedExport
  599. {
  600. public int Property { get; set; }
  601. }
  602. public class DerivedFromBaseWithCustomInheritedExport : BaseClassWithCustomInheritedExport
  603. {
  604. public DerivedFromBaseWithCustomInheritedExport()
  605. {
  606. Property = 43;
  607. }
  608. }
  609. [TestMethod]
  610. public void Test_CustomInheritedExportAttribute_OnBaseClass()
  611. {
  612. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(DerivedFromBaseWithCustomInheritedExport));
  613. var exporter = container.GetExportedValue<BaseClassWithCustomInheritedExport>();
  614. Assert.AreEqual(43, exporter.Property);
  615. }
  616. [InheritedExport("Foo")]
  617. [ExportMetadata("Name", "IFoo1")]
  618. public interface IFoo1 { }
  619. [InheritedExport("Foo")]
  620. [ExportMetadata("Name", "IFoo2")]
  621. public interface IFoo2 { }
  622. [InheritedExport("Foo")]
  623. [ExportMetadata("Name", "FooWithOneFoo")]
  624. public class FooWithOneFoo : IFoo1
  625. {
  626. }
  627. [TestMethod]
  628. public void InheritedExport_OnTypeAndInterface()
  629. {
  630. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(FooWithOneFoo));
  631. var foos = container.GetExports<object, IDictionary<string, object>>("Foo").ToArray();
  632. Assert.AreEqual(1, foos.Length);
  633. Assert.AreEqual("FooWithOneFoo", foos[0].Metadata["Name"]);
  634. }
  635. public class FooWithTwoFoos : IFoo1, IFoo2 { }
  636. [TestMethod]
  637. public void InheritedExport_TwoInterfaces()
  638. {
  639. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(FooWithTwoFoos));
  640. var foos = container.GetExports<object, IDictionary<string, object>>("Foo").ToArray();
  641. Assert.AreEqual(2, foos.Length);
  642. EnumerableAssert.AreEqual(foos.Select(e => (string)e.Metadata["Name"]), "IFoo1", "IFoo2");
  643. }
  644. public class FooWithIfaceByOneFoo : FooWithOneFoo, IFoo1 { }
  645. [TestMethod]
  646. public void InheritedExport_BaseAndInterface()
  647. {
  648. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(FooWithIfaceByOneFoo));
  649. var foos = container.GetExports<object, IDictionary<string, object>>("Foo").ToArray();
  650. Assert.AreEqual(1, foos.Length);
  651. Assert.AreEqual("FooWithOneFoo", foos[0].Metadata["Name"]);
  652. }
  653. [InheritedExport("Foo")]
  654. [ExportMetadata("Name", "FooWithInheritedOnSelf")]
  655. public class FooWithInheritedOnSelf : FooWithOneFoo, IFoo1 { }
  656. [TestMethod]
  657. public void InheritedExport_BaseInterfaceAndSelf()
  658. {
  659. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(FooWithInheritedOnSelf));
  660. var foos = container.GetExports<object, IDictionary<string, object>>("Foo").ToArray();
  661. Assert.AreEqual(1, foos.Length);
  662. Assert.AreEqual("FooWithInheritedOnSelf", foos[0].Metadata["Name"]);
  663. }
  664. [InheritedExport("Foo")]
  665. [ExportMetadata("Name", "IFoo3")]
  666. public interface IFoo3 : IFoo1 { }
  667. public class FooWithInterfaceWithMultipleFoos : IFoo3 { }
  668. [TestMethod]
  669. public void InheritedExport_InterfaceHiearchy()
  670. {
  671. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(FooWithInterfaceWithMultipleFoos));
  672. var foos = container.GetExports<object, IDictionary<string, object>>("Foo").ToArray();
  673. Assert.AreEqual(2, foos.Length);
  674. EnumerableAssert.AreEqual(foos.Select(e => (string)e.Metadata["Name"]), "IFoo1", "IFoo3");
  675. }
  676. [InheritedExport("Foo2")]
  677. [ExportMetadata("Name", "FooWithMultipleInheritedExports")]
  678. public class FooWithMultipleInheritedExports : IFoo1 { }
  679. [TestMethod]
  680. public void InheritedExport_MultipleDifferentContracts()
  681. {
  682. var container = ContainerFactory.CreateWithAttributedCatalog(typeof(FooWithMultipleInheritedExports));
  683. var foos = container.GetExports<object, IDictionary<string, object>>("Foo").ToArray();
  684. Assert.AreEqual(1, foos.Length);
  685. Assert.AreEqual("IFoo1", foos[0].Metadata["Name"]);
  686. var foo2s = container.GetExports<object, IDictionary<string, object>>("Foo2").ToArray();
  687. Assert.AreEqual(1, foo2s.Length);
  688. Assert.AreEqual("FooWithMultipleInheritedExports", foo2s[0].Metadata["Name"]);
  689. }
  690. }
  691. }