es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Estructura c# de referencia circular mediante genéricos.

Al definir una estructura, está claro que el valor del campo de la estructura no puede ser la estructura en sí misma. Además, cuando se definen 2 estructuras y cada una tiene un tipo de campo de la otra, el problema es efectivamente el mismo.

Pero cuando en lugar de establecer directamente el tipo se utiliza un genérico sobre ese tipo, ¿por qué todavía es un problema?

public struct Generic<T> { }
public struct Test1
{
  Generic<Test2> f;
}
public struct Test2
{
  Generic<Test1> f;
}

Este código se compila correctamente y genera un archivo DLL. Cuando intento cargar el archivo DLL, obtengo el mensaje de error ‘Unable to load one or more of the requested types..’ y enumera solo aquellos tipos que tienen la relación descrita anteriormente. Si elimino solo uno de los campos, entonces la carga se realiza con éxito. ¿Qué está sucediendo y cómo solucionarlo?

También noté que el explorador de pruebas de Dotnet no encuentra ninguna prueba siempre que tenga estos tipos genéricos cíclicos, pero presumo que es el mismo problema.

EDITAR:

El código anterior se puede compilar en un archivo DLL. Luego, desde otro proyecto, utilizo System.Runtime.Loader para cargar dinámicamente el archivo DLL:

public static void Main(string[] args)
{ 
  var context = new AssemblyLoadContext("context");
  Assembly assembly = context.LoadFromAssemblyPath("path-to-dll");
  Type[] types = assembly.GetTypes();
}

En la última línea del ejemplo, obtengo la excepción ReflectionTypeLoadException.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El problema con el código anterior radica en que genera una dependencia cíclica entre dos estructuras. Cuando se define una estructura, se le asigna una cierta cantidad de memoria, y si el tamaño de la memoria depende del tamaño de memoria de otra estructura, el tamaño sería infinito, lo que daría lugar a problemas.

    Usar un genérico no resuelve este problema, ya que la dependencia cíclica sigue existiendo, pero a través de medios diferentes. Debido a esta dependencia cíclica, el CLR no puede cargar los tipos adecuadamente y falla la carga.

    Una forma de solucionar este problema sería utilizar una interfaz en lugar de una estructura en uno de los campos. Esto rompe la dependencia cíclica y permite la carga exitosa de los tipos. Por ejemplo:

    public interface IGeneric { }
    public struct Test1
    {
      IGeneric f;
    }
    
    
    public struct Test2
    {
      IGeneric f;
    }
    

    En cuanto al problema con el explorador de pruebas que no encuentra ninguna prueba, es probablemente relacionado con el mismo problema de dependencias cíclicas que lleva a problemas con la carga de los tipos. La solución del problema de dependencia cíclica también debería resolver este problema.

Comments are closed.