C # Assembly.Obciążenie vs montaż.ReflectionOnlyLoad

Staram się zrozumieć różnice między montażem.Obciążenie i montaż.ReflectionOnlyLoad.

W poniższym kodzie próbuję znaleźć wszystkie obiekty w danym zestawie, które dziedziczą po danym interfejsie:

var myTypes = new List<Type>();

var assembly = Assembly.Load("MyProject.Components");

foreach (var type in assembly.GetTypes())
{
   if (type.GetInterfaces().Contains(typeof(ISuperInterface)))
   {
      myTypes.Add(type);
   }
}

Ten kod działa dobrze dla mnie, ale robiłem trochę badań nad innymi, być może lepszymi alternatywami i natknąłem się na Assembly.Metoda ReflectionOnlyLoad ().

Założyłem, że skoro nie Ładuję ani nie wykonuję żadnego z obiektów, zasadniczo po prostu pytając o ich definicje, które mógłbym użyć ReflectionOnlyLoad dla niewielkiego wzrostu wydajności...

Ale okazuje się, że kiedy zmieniam montaż.Załaduj Do Montażu.ReflectionOnlyLoad dostaję następujący błąd podczas wywoływania assembly.GetTypes ():

System.Reflection.ReflectionTypeLoadException:

Nie można załadować jednego lub więcej z żądane typy. / Align = "left" / LoaderExceptions nieruchomości więcej informacje.

Założyłem, że powyższy kod robi tylko refleksję i " patrząc na" biblioteka... ale czy jest to jakiś przykład zasady nieoznaczoności Heisenberga, według której patrzenie na bibliotekę i znajdujące się w niej obiekty próbuje w jakiś sposób utworzyć ich instancję?

Dzięki, Max

Author: David Schmitt, 2008-11-20

5 answers

Zgodnie z odpowiedzią Jona, dobrze byłoby wiedzieć, co jest w LoaderExceptions. Zamiast tej informacji, myślę, że mogę zaryzykować zgadywanie. From MSDN :

Jeśli zespół ma zależności, To Metoda ReflectionOnlyLoad nie załaduj je. Jeśli musisz zbadać musisz sam je załadować.

Musisz dołączyć obsługę do AppDomain.ReflectionOnlyAssemblyResolve, aby pomóc CLR w załadowaniu zależności ładowanego zestawu. Zrobiłeś to?

 24
Author: Kent Boogaart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-27 14:59:20

Uważam, że ogólne zrozumienie różnic między obciążeniem a obciążeniem odbiciowym jest prawidłowe. Problem tutaj (myślę) polega na tym, że nawet aby po prostu załadować Typ, CLR musi odczytać metadane z zestawu, który sam typ jest zdefiniowany w , a także załadować metadane z każdego zestawu, w którym przodkowie typu są zdefiniowani w. Więc musisz zwołać zebranie.ReflectionOnlyLoad na wszystkich składach, które definiują typy, które są przodkami typów, które ładujesz.

To podaj przykład, załóżmy, że masz następującą klasę zdefiniowaną w assembly A.dll.

public class MyBase
{
   public void Foo() { }
}

Oraz następującej klasy zdefiniowanej w zbiorze B.dll.

public class MySubclass : MyBase
{
}

Kiedy zwołujesz Zgromadzenie.GetTypes on assembly B.dll, CLR spróbuje załadować Typ MySubclass i wszystkich jego członków. Ponieważ metoda Foo jest zdefiniowana w MyBase w assembly A.dll (i nie istnieje nigdzie w metadanych B.dll), CLR wyrzuci wyjątki typu load, jeśli montaż A.dll nie został załadowany.

 9
Author: C. Dragon 76,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-20 19:36:59

Metody ReflectionOnly są jedynym sposobem na załadowanie określonego zestawu na dysk do zbadania bez przechodzenia przez zwykłe reguły Load/LoadFrom. Na przykład można załadować zestaw dyskowy o tej samej tożsamości, co w GAC. Jeśli próbowałeś tego z LoadFrom lub LoadFile, zespół GAC jest zawsze załadowany.

DODATKOWO, nie można wywołać GetCustomAttributes(...) na return Assembly instantiate the Attributes on the assembly, which / align = "left" / Musisz w tym celu użyć statycznych metod klasy CustomAttributeData.

Żadne typy w złożeniu załadowanym za pomocą ReflectionOnly nie mogą być utworzone.

 8
Author: x0n,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-20 20:02:54

Żadna metoda nie może być wykonana z assembly, załadowana ReflectionOnlyLoad(), otrzymasz InvalidOperationException. Jest to więc bezpieczny sposób na określenie zawartości złożenia za pomocą odbicia.

 2
Author: abatishchev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-19 13:44:27

Kolejna duża różnica między tymi dwoma jest Assembly.Load dodaje zespół do AppDomain gdzie as Assembly.ReflectionOnlyLoad nie dodaje zespołu do AppDomain

Kod do szczegółowego wyświetlenia.

public void AssemblyLoadTest(string assemblyToLoad)
{
    var initialAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //4

    Assembly.ReflectionOnlyLoad(assemblyToLoad);
    var reflectionOnlyAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //4

    //Shows that assembly is NOT loaded in to AppDomain with Assembly.ReflectionOnlyLoad
    Assert.AreEqual(initialAppDomainAssemblyCount, reflectionOnlyAppDomainAssemblyCount); // 4 == 4

    Assembly.Load(assemblyToLoad);
    var loadAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //5

    //Shows that assembly is loaded in to AppDomain with Assembly.Load
    Assert.AreNotEqual(initialAppDomainAssemblyCount, loadAppDomainAssemblyCount); // 4 != 5
}
 0
Author: Gerrie Pretorius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-13 10:24:17