2016-09-07 3 views
1

J'utilise MEF pour créer des "plugins" pour mon application WPF. Certains de ces plugins que je veux intégrer directement dans le fichier EXE car le fichier EXE doit être autonome. J'utilise Costura by Fody pour intégrer la ressource avec toutes mes autres références. Comme le fichier exe doit être autonome je ne peux pas créer un répertoire pour ces plugins et utiliser le DirectoyCatalogMEF - Obtenir l'assemblage à partir de la DLL intégrée

Y at-il de toute façon que je puisse charger l'assembly à partir de la ressource incorporée, ou simplement spécifier le nom de l'assembly tel que:

catalog.Catalogs.Add(new AssemblyCatalog("My.Assembly.Name)); 

J'ai essayé une boucle à travers les ressources Manifest mais ceux-ci semblent être compressés par Fody:

var resourceNames = GetType().Assembly.GetManifestResourceNames(); 
      foreach (var resourceName in resourceNames) 

Toute aide/suggestions appréciées.

Répondre

2

Ok, donc a que cela fonctionne pour moi, en utilisant la classe ci-dessous (trouvé ce code à https://github.com/Sebazzz/EntityProfiler/blob/master/src/UI/EntityProfiler.Viewer/AppBootstrapper.cs et peaufiné pour répondre à mes besoins):

Pour l'utiliser, vous appelez simplement la fonction d'extraction qui trouvera tout Zip Costura fichiers dans le manifeste de ressources et le décompresse et l'enregistre.

La fonction renvoie un dictionnaire de tous les assemblys correspondant à la chaîne passée dans la fonction. J'itérer ensuite sur eux et ajouter au catalogue à utiliser par conteneur de composition:

var assemblies = CosturaAssemblyExtractor.Extract(AppDomain.CurrentDomain, Assembly.GetExecutingAssembly(), "My.AssemblyName"); 
foreach (var assembly in assemblies) 
{ 
    catalog.Catalogs.Add(new AssemblyCatalog(assembly.Value)); 
} 
container = new CompositionContainer(catalog); 

Classe:

public static class CosturaAssemblyExtractor 
{ 
    public static Dictionary<string, Assembly> Extract(AppDomain OrigDomain, Assembly ExecutingAssembly, string AssemblyStartsWith) 
    { 
     //var currentDomain = origDomain; 
     var assemblies = OrigDomain.GetAssemblies(); 

     var references = new Dictionary<string, Assembly>(); 

     var manifestResourceNames = ExecutingAssembly.GetManifestResourceNames().Where(x => { 
      return x.ToUpper().StartsWith(("costura." + AssemblyStartsWith).ToUpper()) && x.ToUpper().EndsWith(".dll.zip".ToUpper()); 
     }); 

     foreach (var resourceName in manifestResourceNames) 
     { 
      var solved = false; 
      foreach (var assembly in assemblies) 
      { 
       var refName = string.Format("costura.{0}.dll.zip", GetDllName(assembly, true)); 
       if (resourceName.Equals(refName, StringComparison.OrdinalIgnoreCase)) 
       { 
        references[assembly.FullName] = assembly; 
        solved = true; 
        break; 
       } 
      } 

      if (solved) 
       continue; 

      using (var resourceStream = ExecutingAssembly.GetManifestResourceStream(resourceName)) 
      { 
       if (resourceStream == null) continue; 

       if (resourceName.EndsWith(".dll.zip")) 
       { 
        using (var compressStream = new DeflateStream(resourceStream, CompressionMode.Decompress)) 
        { 
         var memStream = new MemoryStream(); 
         CopyTo(compressStream, memStream); 
         memStream.Position = 0; 

         var rawAssembly = new byte[memStream.Length]; 
         memStream.Read(rawAssembly, 0, rawAssembly.Length); 
         var reference = Assembly.Load(rawAssembly); 
         references[reference.FullName] = reference; 
        } 
       } 
       else 
       { 
        var rawAssembly = new byte[resourceStream.Length]; 
        resourceStream.Read(rawAssembly, 0, rawAssembly.Length); 
        var reference = Assembly.Load(rawAssembly); 
        references[reference.FullName] = reference; 
       } 
      } 
     } 
     return references; 
    } 

    private static void CopyTo(Stream source, Stream destination) 
    { 
     var array = new byte[81920]; 
     int count; 
     while ((count = source.Read(array, 0, array.Length)) != 0) 
     { 
      destination.Write(array, 0, count); 
     } 
    } 

    private static string GetDllName(Assembly assembly, bool withoutExtension = false) 
    { 
     var assemblyPath = assembly.CodeBase; 
     return withoutExtension ? Path.GetFileNameWithoutExtension(assemblyPath) : Path.GetFileName(assemblyPath); 
    } 
}