c# reflection assembly.load assembly.reflectiononly

C#Assembly.Load vs Assembly.ReflectionOnlyLoad



(5)

Creo que su comprensión general de las diferencias entre Load y ReflectionOnlyLoad es correcta. El problema aquí (creo) es que incluso para simplemente cargar un tipo, el CLR necesita leer los metadatos del ensamblado en el que se define el tipo , así como cargar los metadatos de cada ensamblaje en el que se definan los antepasados ​​del tipo . Por lo tanto, debe llamar a Assembly.ReflectionOnlyLoad en todos los ensamblados que definan tipos que son ancestros de los tipos que está cargando.

Para dar un ejemplo, suponga que tiene la siguiente clase definida en el conjunto A.dll.

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

y la siguiente clase definida en el conjunto B.dll.

public class MySubclass : MyBase { }

Cuando llame a Assembly.GetTypes en el ensamblado B.dll, el CLR intentará cargar el tipo MySubclass y todos sus miembros. Como el método Foo se define en MyBase en el ensamblado A.dll (y no existe en los metadatos de B.dll), el CLR emitirá las excepciones de carga de tipo si el ensamblado A.dll no se ha cargado.

Estoy tratando de entender las diferencias entre Assembly.Load y Assembly.ReflectionOnlyLoad.

En el siguiente código, intento encontrar todos los objetos en un ensamblaje determinado que hereden de una interfaz determinada:

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); } }

Este código funciona bien para mí, pero estaba investigando otras alternativas posiblemente mejores y encontré el método Assembly.ReflectionOnlyLoad ().

Supuse que como no cargaba ni ejecutaba ninguno de los objetos, básicamente solo preguntaba sobre sus definiciones que podía usar ReflectionOnlyLoad para un ligero aumento en el rendimiento ...

Pero resulta que cuando cambio Assembly.Load a Assembly.ReflectionOnlyLoad aparece el siguiente error cuando se llama assembly.GetTypes ():

System.Reflection.ReflectionTypeLoadException:

No se pueden cargar uno o más de los tipos solicitados. Recupere la propiedad LoaderExceptions para obtener más información.

Supuse que el código anterior SOLO estaba reflexionando y "mirando" a la biblioteca ... pero ¿es esto una especie de instancia del Principio de Incertidumbre de Heisenberg por el cual al mirar la biblioteca y los objetos en ella se está intentando crear una instancia de ellos en alguna parte? ¿camino?

Gracias, Max


Los métodos ReflectionOnly son la única forma de cargar un Assembly específico en el disco para examinar sin pasar por las reglas habituales Load / LoadFrom. Por ejemplo, puede cargar un ensamblaje basado en disco con la misma identidad que uno en el GAC. Si ha intentado esto con LoadFrom o LoadFile, el ensamblado de GAC SIEMPRE está cargado.

Además, no puede llamar a GetCustomAttributes (...) en la instancia de ensamblaje de devolución ya que esto intentará crear instancias de los atributos en el ensamblaje, que son ReflectionOnly. Debe usar los métodos estáticos de la clase CustomAttributeData para esto.

No se pueden crear instancias de ningún tipo en un ensamblaje cargado a través de ReflectionOnly.


No se puede ejecutar ningún método desde el ensamblaje, cargado con ReflectionOnlyLoad() , obtendrá InvalidOperationException . Entonces, esta es una forma segura de determinar el contenido del ensamblaje mediante la reflexión.


Otra gran diferencia entre los dos es Assembly.Load agrega el ensamblado al AppDomain donde Assembly.ReflectionOnlyLoad no agregará el ensamblado al AppDomain

código para mostrar en detalle.

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 }


Según la respuesta de Jon, sería útil saber qué hay en LoaderExceptions . En lugar de esta información, creo que puedo arriesgarme. Desde MSDN :

Si el ensamblado tiene dependencias, el método ReflectionOnlyLoad no las carga. Si necesita examinarlos, debe cargarlos usted mismo.

Debe adjuntar un controlador a AppDomain.ReflectionOnlyAssemblyResolve para ayudar al CLR a cargar las dependencias del ensamblaje que está cargando. ¿Has hecho esto?