ASP.NET MVC 2: Lokalizowanie modelu danych przy użyciu Model MetaData Provider

Jak wiadomo w ASP.NET MVC 2 można określać etykiety poszczególnych właściwości modelu poprzez atrybut DisplayName. W przypadku kiedy chcemy mieć z lokalizowany opis to jest mały problem zwłaszcza jeśli jest potrzeba uruchomić to na .NET 3.5 gdzie DisplayName nie posiada dodatkowych możliwości podana zasobów i etykiet z którego może pobrać opis. A co w przypadku kiedy atrybut ten już ma takie możliwości (.NET 4.0) ale nie ma dostępu do zasobów bo jest w zewnętrznej bibliotece a zasoby są dopiero dostępne w samej aplikacji?
Jednym z działających rozwiązań jest następujące:

...
[DisplayName("X:Code")]
public string Code {get; set;}
...

A więc używając atrybutu DisplayName ustaliłem specjalny zapis nazwy - klucza.
Wykorzystują dostępny model providerów w ASP.NET MVC 2 utworzyłem sobie własny provider który przetwarza atrybuty właściwości w modelu danych. Wyprowadziłem sobie własną klasę z DataAnnotationsModelMetadataProvider w której sprawdzam atrybut DisplayName dla danej właściwości modelu danych i jeśli jest według mojego klucza - wzoru to staram się znaleźć tłumaczenie w lokalnych zasobach aplikacji.


public class LocalizedDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable attributes, Type containerType, Func < object > modelAccessor, Type modelType, string propertyName)
{
var meta = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
if (string.IsNullOrEmpty(propertyName))
{
return meta;
}
if (meta != null && !string.IsNullOrEmpty(meta.DisplayName) && meta.DisplayName.StartsWith("X:", StringComparison.Ordinal))
{
string key = meta.DisplayName.Replace("X:", "");
meta.DisplayName = Resources.Strings.ResourceManager.GetString(key, Resources.Strings.Culture);
if (string.IsNullOrEmpty(meta.DisplayName))
{
meta.DisplayName = key;
}
}
if (string.IsNullOrEmpty(meta.DisplayName))
{
meta.DisplayName = string.Format(CultureInfo.InvariantCulture, "{0}", propertyName);
}
return meta;
}
}

Potem zostaje mi to zarejestrować w aplikacji poprzez plik Global.asax np w ten sposób:

protected void Application_Start()
{
...
ModelMetadataProviders.Current = new LocalizedDataAnnotationsModelMetadataProvider();
...
}

Dzięki takiemu mechanizmowi mogę dynamicznie tłumaczyć opisy właściwości modelu a i model zdefiniować jako nie zależny od zasobów aplikacji.

0 komentarze:

Prześlij komentarz