PageRenderTime 55ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/V4/PrismLibrary/Desktop/Prism/Modularity/AssemblyResolver.Desktop.cs

#
C# | 152 lines | 92 code | 25 blank | 35 comment | 15 complexity | 2955979e0d41a5a264c06d35be4cbc8e MD5 | raw file
  1. //===================================================================================
  2. // Microsoft patterns & practices
  3. // Composite Application Guidance for Windows Presentation Foundation and Silverlight
  4. //===================================================================================
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8. // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9. // FITNESS FOR A PARTICULAR PURPOSE.
  10. //===================================================================================
  11. // The example companies, organizations, products, domain names,
  12. // e-mail addresses, logos, people, places, and events depicted
  13. // herein are fictitious. No association with any real company,
  14. // organization, product, domain name, email address, logo, person,
  15. // places, or events is intended or should be inferred.
  16. //===================================================================================
  17. using System;
  18. using System.Collections.Generic;
  19. using System.IO;
  20. using System.Linq;
  21. using System.Reflection;
  22. using Microsoft.Practices.Prism.Properties;
  23. namespace Microsoft.Practices.Prism.Modularity
  24. {
  25. /// <summary>
  26. /// Handles AppDomain's AssemblyResolve event to be able to load assemblies dynamically in
  27. /// the LoadFrom context, but be able to reference the type from assemblies loaded in the Load context.
  28. /// </summary>
  29. public class AssemblyResolver : IAssemblyResolver, IDisposable
  30. {
  31. private readonly List<AssemblyInfo> registeredAssemblies = new List<AssemblyInfo>();
  32. private bool handlesAssemblyResolve;
  33. /// <summary>
  34. /// Registers the specified assembly and resolves the types in it when the AppDomain requests for it.
  35. /// </summary>
  36. /// <param name="assemblyFilePath">The path to the assemly to load in the LoadFrom context.</param>
  37. /// <remarks>This method does not load the assembly immediately, but lazily until someone requests a <see cref="Type"/>
  38. /// declared in the assembly.</remarks>
  39. public void LoadAssemblyFrom(string assemblyFilePath)
  40. {
  41. if (!this.handlesAssemblyResolve)
  42. {
  43. AppDomain.CurrentDomain.AssemblyResolve += this.CurrentDomain_AssemblyResolve;
  44. this.handlesAssemblyResolve = true;
  45. }
  46. Uri assemblyUri = GetFileUri(assemblyFilePath);
  47. if (assemblyUri == null)
  48. {
  49. throw new ArgumentException(Resources.InvalidArgumentAssemblyUri, "assemblyFilePath");
  50. }
  51. if (!File.Exists(assemblyUri.LocalPath))
  52. {
  53. throw new FileNotFoundException();
  54. }
  55. AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyUri.LocalPath);
  56. AssemblyInfo assemblyInfo = this.registeredAssemblies.FirstOrDefault(a => assemblyName == a.AssemblyName);
  57. if (assemblyInfo != null)
  58. {
  59. return;
  60. }
  61. assemblyInfo = new AssemblyInfo() { AssemblyName = assemblyName, AssemblyUri = assemblyUri };
  62. this.registeredAssemblies.Add(assemblyInfo);
  63. }
  64. private static Uri GetFileUri(string filePath)
  65. {
  66. if (String.IsNullOrEmpty(filePath))
  67. {
  68. return null;
  69. }
  70. Uri uri;
  71. if (!Uri.TryCreate(filePath, UriKind.Absolute, out uri))
  72. {
  73. return null;
  74. }
  75. if (!uri.IsFile)
  76. {
  77. return null;
  78. }
  79. return uri;
  80. }
  81. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom")]
  82. private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
  83. {
  84. AssemblyName assemblyName = new AssemblyName(args.Name);
  85. AssemblyInfo assemblyInfo = this.registeredAssemblies.FirstOrDefault(a => AssemblyName.ReferenceMatchesDefinition(assemblyName, a.AssemblyName));
  86. if (assemblyInfo != null)
  87. {
  88. if (assemblyInfo.Assembly == null)
  89. {
  90. assemblyInfo.Assembly = Assembly.LoadFrom(assemblyInfo.AssemblyUri.LocalPath);
  91. }
  92. return assemblyInfo.Assembly;
  93. }
  94. return null;
  95. }
  96. private class AssemblyInfo
  97. {
  98. public AssemblyName AssemblyName { get; set; }
  99. public Uri AssemblyUri { get; set; }
  100. public Assembly Assembly { get; set; }
  101. }
  102. #region Implementation of IDisposable
  103. /// <summary>
  104. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  105. /// </summary>
  106. /// <remarks>Calls <see cref="Dispose(bool)"/></remarks>.
  107. /// <filterpriority>2</filterpriority>
  108. public void Dispose()
  109. {
  110. this.Dispose(true);
  111. GC.SuppressFinalize(this);
  112. }
  113. /// <summary>
  114. /// Disposes the associated <see cref="AssemblyResolver"/>.
  115. /// </summary>
  116. /// <param name="disposing">When <see langword="true"/>, it is being called from the Dispose method.</param>
  117. protected virtual void Dispose(bool disposing)
  118. {
  119. if (this.handlesAssemblyResolve)
  120. {
  121. AppDomain.CurrentDomain.AssemblyResolve -= this.CurrentDomain_AssemblyResolve;
  122. this.handlesAssemblyResolve = false;
  123. }
  124. }
  125. #endregion
  126. }
  127. }