2008-12-20 6 views
107

ASP.NET uygulamasında, veritabanı bağlantılarını/bağlantılarını doğrulamak, geçerli uygulama ayarlarını ve Bağlantıları incelemek vb. Gibi şeyler yapan bir "tanılama" sayfası var. Bu sayfanın bir bölümü önemli türlerin Montaj sürümlerini görüntüler. boyunca kullanıldı, ancak yüklü derlemelerin TÜM sürümlerini etkili bir şekilde nasıl göstereceğimi anlayamadım.Şu anda yüklü olan derlemeler arasında nasıl geçiyorsunuz?

numaralı telefonu anlamaya yönelik en etkili yöntem şu anda başvuran ve/veya yüklenmiş olan bir .NET uygulaması içinde Montajları nedir?

Not: Belirli bir dizinde * .dll ile yineleme gibi dosya tabanlı yöntemlerle ilgilenmiyorum. Uygulamanın aslında şu anda'u kullanarak ne olduğunu merak ediyorum.

cevap

16

Bu uzantı yöntemi, iç içe geçmiş derlemeler de dahil olmak üzere yinelemeli olarak başvurulan tüm derlemeleri toplar.

ReflectionOnlyLoad kullandığı için, derlemeleri, JIT işlemine müdahale etmeme avantajına sahip ayrı bir AppDomain'de yükler.

Ayrıca bir MyGetMissingAssembliesRecursive olduğunu fark edeceksiniz. Geçerli bir dizinde başvurulan ancak herhangi bir nedenle bulunmayan eksik derlemeleri algılamak için bunu kullanabilirsiniz. Bu, MEF kullanılırken son derece kullanışlıdır. İade listesi, hem eksik montajı hem de sahibi olanı (ebeveyn) verecektir.

/// <summary> 
///  Intent: Get referenced assemblies, either recursively or flat. Not thread safe, if running in a multi 
///  threaded environment must use locks. 
/// </summary> 
public static class GetReferencedAssemblies 
{ 
    static void Demo() 
    { 
     var referencedAssemblies = Assembly.GetEntryAssembly().MyGetReferencedAssembliesRecursive(); 
     var missingAssemblies = Assembly.GetEntryAssembly().MyGetMissingAssembliesRecursive(); 
     // Can use this within a class. 
     //var referencedAssemblies = this.MyGetReferencedAssembliesRecursive(); 
    } 

    public class MissingAssembly 
    { 
     public MissingAssembly(string missingAssemblyName, string missingAssemblyNameParent) 
     { 
      MissingAssemblyName = missingAssemblyName; 
      MissingAssemblyNameParent = missingAssemblyNameParent; 
     } 

     public string MissingAssemblyName { get; set; } 
     public string MissingAssemblyNameParent { get; set; } 
    } 

    private static Dictionary<string, Assembly> _dependentAssemblyList; 
    private static List<MissingAssembly> _missingAssemblyList; 

    /// <summary> 
    ///  Intent: Get assemblies referenced by entry assembly. Not recursive. 
    /// </summary> 
    public static List<string> MyGetReferencedAssembliesFlat(this Type type) 
    { 
     var results = type.Assembly.GetReferencedAssemblies(); 
     return results.Select(o => o.FullName).OrderBy(o => o).ToList(); 
    } 

    /// <summary> 
    ///  Intent: Get assemblies currently dependent on entry assembly. Recursive. 
    /// </summary> 
    public static Dictionary<string, Assembly> MyGetReferencedAssembliesRecursive(this Assembly assembly) 
    { 
     _dependentAssemblyList = new Dictionary<string, Assembly>(); 
     _missingAssemblyList = new List<MissingAssembly>(); 

     InternalGetDependentAssembliesRecursive(assembly); 

     // Only include assemblies that we wrote ourselves (ignore ones from GAC). 
     var keysToRemove = _dependentAssemblyList.Values.Where(
      o => o.GlobalAssemblyCache == true).ToList(); 

     foreach (var k in keysToRemove) 
     { 
      _dependentAssemblyList.Remove(k.FullName.MyToName()); 
     } 

     return _dependentAssemblyList; 
    } 

    /// <summary> 
    ///  Intent: Get missing assemblies. 
    /// </summary> 
    public static List<MissingAssembly> MyGetMissingAssembliesRecursive(this Assembly assembly) 
    { 
     _dependentAssemblyList = new Dictionary<string, Assembly>(); 
     _missingAssemblyList = new List<MissingAssembly>(); 
     InternalGetDependentAssembliesRecursive(assembly); 

     return _missingAssemblyList; 
    } 

    /// <summary> 
    ///  Intent: Internal recursive class to get all dependent assemblies, and all dependent assemblies of 
    ///  dependent assemblies, etc. 
    /// </summary> 
    private static void InternalGetDependentAssembliesRecursive(Assembly assembly) 
    { 
     // Load assemblies with newest versions first. Omitting the ordering results in false positives on 
     // _missingAssemblyList. 
     var referencedAssemblies = assembly.GetReferencedAssemblies() 
      .OrderByDescending(o => o.Version); 

     foreach (var r in referencedAssemblies) 
     { 
      if (String.IsNullOrEmpty(assembly.FullName)) 
      { 
       continue; 
      } 

      if (_dependentAssemblyList.ContainsKey(r.FullName.MyToName()) == false) 
      { 
       try 
       { 
        var a = Assembly.ReflectionOnlyLoad(r.FullName); 
        _dependentAssemblyList[a.FullName.MyToName()] = a; 
        InternalGetDependentAssembliesRecursive(a); 
       } 
       catch (Exception ex) 
       { 
        _missingAssemblyList.Add(new MissingAssembly(r.FullName.Split(',')[0], assembly.FullName.MyToName())); 
       } 
      } 
     } 
    } 

    private static string MyToName(this string fullName) 
    { 
     return fullName.Split(',')[0]; 
    } 
} 

Güncelleme

bu kod parçacığı güvenli hale getirmek için, onun etrafında bir lock koydu. Büyüsünü yapmak için paylaşılan statik bir global değişkeni referans aldığı için şu anda varsayılan olarak güvenli değil.

+0

Sadece bu iş parçacığı güvenli olması için yeniden yazdı, bu yüzden aynı anda birçok farklı konudan çağrılabilir (neden bunu isteyeceğinizden emin değilim, ama hey, daha güvenli). Kodu göndermemi istersen bana haber ver. – Contango

+1

da güncellenmiş sürümünüzü de gönderebilir – Michael

+1

@Contango Thread güvenli sürümünüzü yayınlayabilir misiniz, ya da bu konuda bir blog yazdıysanız, bunu yayınlayabilir misiniz? – Robert

176

akım AppDomain için meclisleri yüklenen Başlarken: montaj A referansları montaj B ve montaj Dolu ise

var referencedAssemblies = someAssembly.GetReferencedAssemblies(); 

yapar Not olun:

var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); 

başka meclisi tarafından başvurulan derlemeler alınıyor montaj B'nin de yüklü olduğunu ima etmez. Montaj B sadece gerektiğinde ve gerektiğinde yüklenir. Bu nedenle, GetReferencedAssemblies(), Assembly örneklerinden ziyade AssemblyName örneğini döndürür.

+1

Bunun gibi bir şeye ihtiyacım var - bir .net çözümü verildiğinde, tüm projelerde başvurulan tüm derlemeleri bulmak istiyorum. Fikirler? –

+0

Lütfen her iki yöntemin aslında kullanılan dll'leri listelediğini unutmayın. Açıkçası, kullanılmayan çözümlerde referanslara sahip olmak anlamsızdır, ancak bu kişi birileri TÜM meclisleri aracılığıyla spekülatif olarak taramaya çalışırken kafa karıştırıcı olabilir. Tüm meclisler görünmeyebilir. – Pompair

+0

@Kumar Vaibhav Sadece bunu yapan bir cevap ekledim. – Contango