Estoy buscando una forma de localizar los nombres de las propiedades que se muestran en un PropertyGrid. El nombre de la propiedad puede ser "anulado" mediante el atributo DisplayNameAttribute. Desafortunadamente, los atributos no pueden tener expresiones no constantes. Entonces no puedo usar recursos fuertemente tipados como:
class Foo
{
[DisplayAttribute(Resources.MyPropertyNameLocalized)] // do not compile
string MyProperty {get; set;}
}
Eché un vistazo y encontré una sugerencia para heredar de DisplayNameAttribute para poder usar el recurso. Terminaría con un código como:
class Foo
{
[MyLocalizedDisplayAttribute("MyPropertyNameLocalized")] // not strongly typed
string MyProperty {get; set;}
}
Sin embargo, pierdo beneficios de recursos fuertemente tipificados, lo que definitivamente no es algo bueno. Luego me encontré con DisplayNameResourceAttribute, que puede ser lo que estoy buscando. Pero se supone que debe estar en el espacio de nombres Microsoft.VisualStudio.Modeling.Design y no puedo encontrar qué referencia se supone que debo agregar para este espacio de nombres.
¿Alguien sabe si hay una manera más fácil de lograr la localización de DisplayName de una buena manera? ¿O si hay alguna forma de usar lo que Microsoft parece estar usando para Visual Studio?
fuente
Respuestas:
Existe el atributo Display de System.ComponentModel.DataAnnotations en .NET 4. Funciona en MVC 3
PropertyGrid
.Esto busca un recurso nombrado
UserName
en suMyResources
archivo .resx.fuente
typeof(MyResources)
, es posible que deba establecer el modificador de acceso al archivo de recursos en Público .Estamos haciendo esto para varios atributos con el fin de admitir varios idiomas. Hemos adoptado un enfoque similar a Microsoft, donde anulan sus atributos básicos y pasan un nombre de recurso en lugar de la cadena real. A continuación, el nombre del recurso se utiliza para realizar una búsqueda en los recursos DLL para que vuelva la cadena real.
Por ejemplo:
Puede llevar esto un paso más allá cuando realmente use el atributo y especificar los nombres de sus recursos como constantes en una clase estática. De esa manera, obtienes declaraciones como.
La actualización
ResourceStrings
se vería así (tenga en cuenta que cada cadena se referirá al nombre de un recurso que especifica la cadena real):fuente
[MyNamespace].[MyResourceFile].ResourceManager.GetString("MyString");
Aquí está la solución con la que terminé en un ensamblado separado (llamado "Común" en mi caso):
con el código para buscar el recurso:
El uso típico sería:
Lo que es bastante feo ya que uso cadenas literales para la clave de recursos. Usar una constante allí significaría modificar Resources.Designer.cs, lo que probablemente no sea una buena idea.
Conclusión: no estoy contento con eso, pero estoy aún menos contento con Microsoft, que no puede proporcionar nada útil para una tarea tan común.
fuente
ResourceManager
propiedades. En su lugar, puede simplemente obtener la propiedad directamente del tipo proporcionado en el parámetro:PropertyInfo property = resourceManagerProvider.GetProperty(resourceKey, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
Usando el atributo Display (de System.ComponentModel.DataAnnotations) y la expresión nameof () en C # 6, obtendrá una solución localizada y fuertemente tipada.
fuente
Puede usar T4 para generar constantes. Escribí uno:
fuente
Esta es una pregunta antigua, pero creo que es un problema muy común y aquí está mi solución en MVC 3.
En primer lugar, se necesita una plantilla T4 para generar constantes y evitar cadenas desagradables. Tenemos un archivo de recursos 'Labels.resx' que contiene todas las cadenas de etiquetas. Por lo tanto, la plantilla T4 usa el archivo de recursos directamente,
Luego, se crea un método de extensión para localizar el 'DisplayName',
El atributo 'DisplayName' se reemplaza por el atributo 'DisplayLabel' para leer de 'Labels.resx' automáticamente,
Después de todo ese trabajo de preparación, es hora de tocar esos atributos de validación predeterminados. Estoy usando el atributo 'Requerido' como ejemplo,
Ahora, podemos aplicar esos atributos en nuestro modelo,
De forma predeterminada, el nombre de la propiedad se usa como clave para buscar 'Label.resx', pero si lo configura a través de 'DisplayLabel', lo usará en su lugar.
fuente
Puede crear una subclase de DisplayNameAttribute para proporcionar i18n, anulando uno de los métodos. Al igual que. editar: Puede que tenga que conformarse con usar una constante para la clave.
fuente
Yo uso de esta manera resolver en mi caso
Con el codigo
fuente
Bueno, la asamblea es
Microsoft.VisualStudio.Modeling.Sdk.dll
. que viene con el SDK de Visual Studio (con el paquete de integración de Visual Studio).Pero se usaría prácticamente de la misma manera que su atributo; no hay forma de utilizar recursos de tipos fuertes en atributos simplemente porque no son constantes.
fuente
Pido disculpas por el código VB.NET, mi C # está un poco oxidado ... Pero entenderás la idea, ¿verdad?
En primer lugar, cree una nueva clase:,
LocalizedPropertyDescriptor
que heredaPropertyDescriptor
. Anule laDisplayName
propiedad de esta manera:Some.ResourceManager
es el ResourceManager del archivo de recursos que contiene sus traducciones.A continuación, implemente
ICustomTypeDescriptor
en la clase con las propiedades localizadas y anule elGetProperties
método:Ahora puede usar el atributo 'DisplayName` para almacenar una referencia a un valor en un archivo de recursos ...
prop_description
es la clave en el archivo de recursos.fuente