Pregunta

Durante una refactorización, agregué un parámetro de tipo genérico a MyControl, una clase derivada de UserControl . Entonces mi clase ahora es MyControl<T>.

Ahora aparece un error en tiempo de ejecución que indica que el archivo de recursos incrustado MyControl`1.resources no se puede encontrar. Una mirada rápida con .NET Reflector muestra que el archivo de recursos en realidad se llama MyControl. recursos , sin el `1 .

Al comienzo del método MyControl<T>.InitializeComponent existe esta línea que probablemente sea la que causa problemas:

 System.ComponentModel.ComponentResourceManager resources =
    new System.ComponentModel.ComponentResourceManager(
       typeof(MyControl<>));

¿Cómo fuerzo a ComponentResourceManager a usar el archivo de recursos incrustado MyControl.resources? También son bienvenidas otras formas de resolver este problema.

¿Fue útil?

Solución

Además de la técnica de Wim, también puede declarar un control base no genérico que tenga el mismo nombre que su clase genérica, y que su control / forma genérica se derive de esa clase base no genérica.

De esta manera, puede engañar al diseñador y al compilador para que utilicen el archivo de recursos de su clase genérica, y obtiene soporte permanente para el diseñador una vez que se configura la clase base sin tener que manipular el archivo .designer cada vez que reconstruye:

// Empty stub class, must be in a different file (added as a new class, not UserControl 
// or Form template)
public class MyControl : UserControl
{
}

// Generic class
public class MyControl<T> : MyControl
{
     // ...
}

Los únicos requisitos son tener exactamente el mismo nombre para su clase genérica y su clase base, y que la clase base debe estar en otro archivo de clase, de lo contrario, el diseñador se queja de no encontrar uno de las dos clases.

PS. Probé esto con formularios, pero debería funcionar igual con los controles.

Otros consejos

Resulta que puede anular el nombre de archivo del recurso para cargar heredando de ComponentResourceManager de esta manera:

   using System;
   using System.ComponentModel;

   internal class CustomComponentResourceManager : ComponentResourceManager
   {
      public CustomComponentResourceManager(Type type, string resourceName)
         : base(type)
      {
         this.BaseNameField = resourceName;
      }
   }

Ahora puedo asegurarme de que el administrador de recursos cargue MyControl.resources así:

 System.ComponentModel.ComponentResourceManager resources =
    new CustomComponentResourceManager(typeof(MyControl<>), "MyControl");

Esto parece funcionar.

editar : la línea anterior se sobrescribe si usa el diseñador, porque está en el región de código generado. Evito al diseñador y uso herramientas de control de versiones para revertir cualquier cambio no deseado, pero la solución no es la ideal.

En mi Visual & nbsp; Studio & nbsp; 2008 Tengo este error:

  

Recursos System.ComponentModel.ComponentResourceManager = nuevo System.ComponentModel.ComponentResourceManager (typeof (MyControl));

El uso del tipo genérico 'WindowsFormsApplication1.UserControl1' requiere argumentos de tipo '1'.

Observe que en mi caso el código se generó sin paréntesis, <>, después del nombre de la clase.

Se está volviendo interesante, vea ImageList autogenera no- compilar código en un Control de usuario genérico .

Lo que dijeron:

  

Publicado por Microsoft el 6/7/2005 a las 2:49 p. m.

     

Este es un error interesante. Has encontrado un scneario genérico que no admitimos en el diseñador de formularios Windows Forms. No podremos agregar soporte para esto en la versión Whidbey (mi nota: Visual & Nbsp; Studio & Nbsp; 2008?). Consideraremos esto para una versión futura. Como solución alternativa, puede usar el diseñador para crear un UserControl no genérico con una propiedad Type pública y luego crear una clase genérica que herede de ella y pase T a la propiedad Type de las clases base.

Supongo que este control no puede diseñarse en Visual & nbsp; tampoco en el diseñador de formularios de Studio.

La solución más simple y fácil es crear una clase ficticia para el typeof() autogenerado. No necesita heredar de él o incluso exponerlo al exterior:

// Non-generic name so that autogenerated resource loading code is happy
internal sealed class GridEditorForm
{
}

(En mi experiencia, el tiempo requerido para que el diseñador trabaje en torno a los genéricos no valió la frialdad ideal que los genéricos pueden proporcionar. No volveré a utilizar formularios o controles genéricos de Windows).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top