Zjištění seznamu načtených assembly v Silverlight aplikaci

Tomáš Holan       24. 4. 2011       Silverlight, Reflexe       6404 zobrazení

Asi je známou věcí, že .NET Framework ve verzi pro Silverlight neobsahuje úplně všechny metody a neumožňuje úplně všechny možnosti jako standardní “velký” framework. Důvody jsou v celku jasné např. izolace Silvelight aplikace v tzv. sandboxu, nároky na bezpečnost a snaha o to, aby byl Silverlight plugin co nejmenší. Jedno z chybějících API je i získání seznamu aktuálně načtených assembly:

internal static class TypeHelper
{
    #region action methods
    public static Type GetType(string typeName)
    {
        foreach (var assembly in GetLoadedAssemblies())
        {
            var type = assembly.GetType(typeName, false);
            if (type != null)
            {
                return type;
            }
        }

        return null;
    }
    #endregion

    #region private member functions
    private static IEnumerable<System.Reflection.Assembly> GetLoadedAssemblies()
    {
        return AppDomain.CurrentDomain.GetAssemblies(); //<—-not supported in Silverlight!
    }
    #endregion
}

To je užitečné pokud potřebujeme vrátit objekt typu Type pro string, který obsahuje název datového typu (type name qualified by its namespace – např. “System.Windows.Application”), ale nikoliv jméno typu včetně názvu assembly (assembly-qualified name – např. “System.Windows.Application, System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e”) tj. jinými slovy neznáme z jaké assembly daný typ pochází (*).

Výše uvedený kód to právě řeší tak, že prochází všechny aktuálně načtené assembly a typ hledá postupně v nich. To, že příslušná assembly bude v dané chvíli načtena, se v běžném případě dá považovat za rozumný předpoklad.

Jak tedy vrátit seznam načtených assembly v Silverlightu tj. nahradit nepodporované volání:

AppDomain.CurrentDomain.GetAssemblies();

Základem řešení je manifest .xap balíčku Silverlight aplikace, který umožňuje jako tzv. parts vrátit assembly, které jsou v něm obsažené:

var assemblies = from part in System.Windows.Deployment.Current.Parts
                 let resourceStream = System.Windows.Application.GetResourceStream(new Uri(part.Source, UriKind.Relative))
                 select new System.Windows.AssemblyPart().Load(resourceStream.Stream);

Je tu ale ještě jeden problém a tím je to, že toto vrací pouze assembly jiné než z Silverlight runtime, které se v .xap balíčku nenachází. Konkrétně se jedná o tyto assembly:

  • mscorlib.dll
  • system.dll
  • System.Core.dll
  • System.Net.dll
  • System.Runtime.Serialization.dll
  • System.ServiceModel.dll
  • System.ServiceModel.Web.dll
  • System.Windows.dll
  • System.Windows.Browser.dll
  • System.Xml.dll

Z adresáře:
C:\Program Files (x86)\Microsoft Silverlight\<verze Silverlight>
resp. z adresáře:
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0

V podstatě nezbývá nic jiného než tyto assembly resp. ty důležité z nich (např. pouze ty referencované v našem projektu) k seznamu “navrdo” přidat. Finální řešení bude potom vypadat takto:

internal static class TypeHelper
{
    #region action methods
    public static Type GetType(string typeName)
    {
        foreach (var assembly in GetLoadedAssemblies())
        {
            var type = assembly.GetType(typeName, false);
            if (type != null)
            {
                return type;
            }
        }

        return null;
    }
    #endregion

    #region private member functions
    private static IEnumerable<System.Reflection.Assembly> GetLoadedAssemblies()
    {
#if !SILVERLIGHT
        return AppDomain.CurrentDomain.GetAssemblies();
#else
        foreach (var assembly in new[] 
                                 { 
                                     typeof(string).Assembly,                       //mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e (mscorlib.dll)
                                     typeof(Uri).Assembly,                          //System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e (System.dll)
                                     typeof(System.Linq.Enumerable).Assembly,       //System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e (System.Core.dll)
                                     typeof(System.Net.WebRequest).Assembly,        //System.Net, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e (System.Net.dll)
                                     typeof(System.Windows.Application).Assembly    //System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e (System.Windows.dll)
                                 })
        {
            yield return assembly;
        }

        foreach (var part in System.Windows.Deployment.Current.Parts)
        {
            var resourceStream = System.Windows.Application.GetResourceStream(new Uri(part.Source, UriKind.Relative));
            yield return new System.Windows.AssemblyPart().Load(resourceStream.Stream);
        }
#endif
    }
    #endregion
}

(*) V našem případě nemůžeme použít pouze volání metody Type.GetType(typeName, false), protože tato metoda právě potřebuje specifikovat plné jméno typu včetně assembly (assembly-qualified name).

Jak je uvedeno v MSDN dokumentaci, je totiž v případě uvedení pouze jména typu (type name qualified by its namespace), daný typ vrácen pouze z aktuálně běžící assembly nebo z assembly Mscorlib.dll.

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback