PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/V2.2/trunk/CAL/Desktop/Composite/Modularity/AssemblyResolver.Desktop.cs

#
C# | 155 lines | 95 code | 25 blank | 35 comment | 15 complexity | b1b70a69f43c817dacbecb5e9c7bf47a 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 System.Security.Permissions;
  23. using Microsoft.Practices.Composite.Properties;
  24. namespace Microsoft.Practices.Composite.Modularity
  25. {
  26. /// <summary>
  27. /// Handles AppDomain's AssemblyResolve event to be able to load assemblies dynamically in
  28. /// the LoadFrom context, but be able to reference the type from assemblies loaded in the Load context.
  29. /// </summary>
  30. [SecurityPermission(SecurityAction.LinkDemand)]
  31. [SecurityPermission(SecurityAction.InheritanceDemand)]
  32. public class AssemblyResolver : IAssemblyResolver, IDisposable
  33. {
  34. private readonly List<AssemblyInfo> registeredAssemblies = new List<AssemblyInfo>();
  35. private bool handlesAssemblyResolve;
  36. /// <summary>
  37. /// Registers the specified assembly and resolves the types in it when the AppDomain requests for it.
  38. /// </summary>
  39. /// <param name="assemblyFilePath">The path to the assemly to load in the LoadFrom context.</param>
  40. /// <remarks>This method does not load the assembly immediately, but lazily until someone requests a <see cref="Type"/>
  41. /// declared in the assembly.</remarks>
  42. public void LoadAssemblyFrom(string assemblyFilePath)
  43. {
  44. if (!this.handlesAssemblyResolve)
  45. {
  46. AppDomain.CurrentDomain.AssemblyResolve += this.CurrentDomain_AssemblyResolve;
  47. this.handlesAssemblyResolve = true;
  48. }
  49. Uri assemblyUri = GetFileUri(assemblyFilePath);
  50. if (assemblyUri == null)
  51. {
  52. throw new ArgumentException(Resources.InvalidArgumentAssemblyUri, "assemblyFilePath");
  53. }
  54. if (!File.Exists(assemblyUri.LocalPath))
  55. {
  56. throw new FileNotFoundException();
  57. }
  58. AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyUri.LocalPath);
  59. AssemblyInfo assemblyInfo = this.registeredAssemblies.FirstOrDefault(a => assemblyName == a.AssemblyName);
  60. if (assemblyInfo != null)
  61. {
  62. return;
  63. }
  64. assemblyInfo = new AssemblyInfo() { AssemblyName = assemblyName, AssemblyUri = assemblyUri };
  65. this.registeredAssemblies.Add(assemblyInfo);
  66. }
  67. private static Uri GetFileUri(string filePath)
  68. {
  69. if (String.IsNullOrEmpty(filePath))
  70. {
  71. return null;
  72. }
  73. Uri uri;
  74. if (!Uri.TryCreate(filePath, UriKind.Absolute, out uri))
  75. {
  76. return null;
  77. }
  78. if (!uri.IsFile)
  79. {
  80. return null;
  81. }
  82. return uri;
  83. }
  84. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom")]
  85. private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
  86. {
  87. AssemblyName assemblyName = new AssemblyName(args.Name);
  88. AssemblyInfo assemblyInfo = this.registeredAssemblies.FirstOrDefault(a => AssemblyName.ReferenceMatchesDefinition(assemblyName, a.AssemblyName));
  89. if (assemblyInfo != null)
  90. {
  91. if (assemblyInfo.Assembly == null)
  92. {
  93. assemblyInfo.Assembly = Assembly.LoadFrom(assemblyInfo.AssemblyUri.LocalPath);
  94. }
  95. return assemblyInfo.Assembly;
  96. }
  97. return null;
  98. }
  99. private class AssemblyInfo
  100. {
  101. public AssemblyName AssemblyName { get; set; }
  102. public Uri AssemblyUri { get; set; }
  103. public Assembly Assembly { get; set; }
  104. }
  105. #region Implementation of IDisposable
  106. /// <summary>
  107. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  108. /// </summary>
  109. /// <remarks>Calls <see cref="Dispose(bool)"/></remarks>.
  110. /// <filterpriority>2</filterpriority>
  111. public void Dispose()
  112. {
  113. this.Dispose(true);
  114. GC.SuppressFinalize(this);
  115. }
  116. /// <summary>
  117. /// Disposes the associated <see cref="AssemblyResolver"/>.
  118. /// </summary>
  119. /// <param name="disposing">When <see langword="true"/>, it is being called from the Dispose method.</param>
  120. protected virtual void Dispose(bool disposing)
  121. {
  122. if (this.handlesAssemblyResolve)
  123. {
  124. AppDomain.CurrentDomain.AssemblyResolve -= this.CurrentDomain_AssemblyResolve;
  125. this.handlesAssemblyResolve = false;
  126. }
  127. }
  128. #endregion
  129. }
  130. }