В первой части я показал пример простого создания шаблона и его генерация в файл. Теперь, расскажу о дополнительных, интересных свойствах StringTemplate.
Скиннинг или наследование шаблонов
В StringTemplate предусмотрено наследование шаблонов. Предположим, вы создаете сайт с разным дизайном, или на разных языках. В таком случае, можно создать осную папку шаблонов (в моем примере — это super), и папку «скин»-а (в примере, это default). Шаблонизатор, в таком случае, будет искать все файлы сначала в папке default, а при их отсутствии — в super. Задать наследование можно с помощью свойства StringTemplateGroup.SuperGroup, примерно так:
superGroup = new StringTemplateGroup("super", TEMPLATES_URL + @"\super");
skinGroup = new StringTemplateGroup(skin, TEMPLATES_URL + @"\" + skin);
skinGroup.SuperGroup = superGroup;
Локализация
В дополнение к наследованию, локализацию можно сделать приближенной к обычному ASP.NET — с помощью ресурс файлов. Несмотря на то, что на сайте StringTemplate есть много примеров локализации на разных языках. На прямую с ResourceManager он работать не стал (это просто не предусмотрено — подробней об этом в !третей части!), из за этого я использую вот такой класс:
public class ResourceManagerWrapper
{
public static ResourceManagerWrapper Create(string resourceName, CultureInfo culture = null)
{
var fullResourceName = Assembly.GetExecutingAssembly().GetName().Name + "." + resourceName;
return new ResourceManagerWrapper(
new ResourceManager(fullResourceName, Assembly.GetExecutingAssembly()),
culture); //берем ресурс по названию из текущей сборки
}
public CultureInfo Culture;
public ResourceManager Manager;
public StringIndexer Strings;
public ObjectIndexer Objects;
public StreamIndexer Streams;
public ResourceManagerWrapper(ResourceManager manager, CultureInfo culture = null)
{
this.Manager = manager;
if (culture == null) culture = new CultureInfo("EN");
this.Culture = culture;
//вот тут добавляем индексацию
Strings = new StringIndexer(Manager);
Objects = new ObjectIndexer(Manager);
Streams = new StreamIndexer(Manager);
}
public ResourceSet TranslationsSet
{
get
{
return Manager.GetResourceSet(Culture, false, true);
}
}
public class ObjectIndexer : StringTemplateDictionary<object>
{
ResourceManager manager;
public ObjectIndexer(ResourceManager manager)
{
this.manager = manager;
}
public override object Get(string key)
{
return manager.GetObject(key);
}
}
public class StreamIndexer : StringTemplateDictionary<Stream>
{
ResourceManager manager;
public StreamIndexer(ResourceManager manager)
{
this.manager = manager;
}
public override Stream Get(string key)
{
return manager.GetStream(key);
}
}
public class StringIndexer : StringTemplateDictionary<string>
{
ResourceManager manager;
public StringIndexer(ResourceManager manager)
{
this.manager = manager;
}
public override string Get(string key)
{
return manager.GetString(key);
}
}
}
StringTemplateDictionary это своего рода класс-заглушка с интерфейсом IDictionary, выглядит который вот так:
public abstract class StringTemplateDictionary<V> : IDictionary
{
public abstract V Get(string key);
public object this[object key]
{
get
{
return Get(key.ToString());
}
set
{
throw new NotImplementedException();
}
}
public void Add(object key, object value)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(object key)
{
return this[key] != null;
}
public IDictionaryEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
public bool IsFixedSize
{
get { throw new NotImplementedException(); }
}
public bool IsReadOnly
{
get { return true; }
}
public ICollection Keys
{
get { throw new NotImplementedException(); }
}
public void Remove(object key)
{
throw new NotImplementedException();
}
public ICollection Values
{
get { throw new NotImplementedException(); }
}
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public int Count
{
get { throw new NotImplementedException(); }
}
public bool IsSynchronized
{
get { throw new NotImplementedException(); }
}
public object SyncRoot
{
get { throw new NotImplementedException(); }
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
Таким образом, появляется возможность передать ресурс как словарь:
var translations = ResourceManagerWrapper.Create("Translations", culture);
page.SetAttribute("strings", translations.Strings);
И теперь использовать, как список — $strings.resourceName$
Инициализация
В итоге, собрав все вместе, мы получаем класс для инициализации и сохранения, который делает следующее:
- Создает экземпляр шаблона по имени.
- Инициализирует группы для поддержки скина.
- На основе культуры, добавляет ресурсы.
- Сохраняет результат работы в файл.
- Настройка финальной обработки (поговорим о ней в третей части).
Метки:C#, OpenSource, Template
Похожие статьи
- 23 сентября 2011 -- Конфигурационные секции. Web.config и App.config для «C# продолжающих». (0)
- 31 августа 2009 -- CRUD на SQLite (5)
- 27 ноября 2009 -- ASP.NET пейджинг. (Paging in ASP.NET) (3)
- 4 февраля 2009 -- LINQ Insert or Update еще одно решение. (2)
- 22 августа 2008 -- Собственная страница для обработки ошибок на ASP.NET (0)

