Мне кажется, что вы можете использовать дженерики для достижения того, что вы хотите.
Так что в базе у вас будет
protected virtual string GetFormattedAttribute<T>(string propertyName, T propertyValue)
Это было бы полезно, если бы у всех типов было какое-то общее общее форматирование.
Это кажется хорошим при первоначальной проверке, но что если у ваших типов нет какого-либо общего шаблона форматирования (что, я полагаю, имеет место).Вместо того, чтобы реализовывать все форматирование в одном классе, я бы скорее разделил и победил, реализовав несколько небольших специализированных форматированных классов, тесно связанных с типом, который они форматируют.Такие классы будут реализовывать универсальный интерфейс IPropertyFormatter<T>
public interface IPropertyFormatter<T> {
string FormatValue(T value);
}
Наиболее универсальный класс, который потребуется для реализации этого интерфейса, - это просто когда вы делаете для Object.ToString()
значение, поэтому у нас есть ObjectPropertyFormatterкак наиболее общая реализация IPropertyFormatter
public class ObjectPropertyFormatter : IPropertyFormatter<Object>
{
public string FormatValue(Object value)
{
//object fallback formatting logic
return value.ToString();
}
}
Теперь предположим, что некоторые типы требуют специальной обработки.Затем мы реализуем специальные средства форматирования свойств для них.Поэтому вместо того, чтобы иметь один класс с тоннами перегрузок для всех конкретных случаев, у вас есть выделенные классы, которые обрабатывают логику форматирования.В этом примере есть DateTimePropertyFormatter
и BooleanPropertyFormatter
, и они будут реализованы следующим образом:
public class DateTimePropertyFormatter : IPropertyFormatter<DateTime>
{
public string FormatValue(DateTime value)
{
//DateTime customised formatting logic
return "<b>" + value.ToString("yyyyMMdd") + "</b>";
}
}
public class BoolPropertyFormatter : IPropertyFormatter<bool>
{
public string FormatValue(bool value)
{
//bool customised formatting logic
if (value)
return "yeaaah";
else
return "nope";
}
}
У вас может быть много других классов, таких как List и т. Д., Каждый со своей логикой форматированиясоблюдение принципа единой ответственности
Правильно, поэтому у нас есть наши средства форматирования, как нам заставить работать все наши средства форматирования?Это где FormatterResolver
вступает в игру.Вы можете зарегистрировать средства форматирования, и они будут
/// <summary>
/// Class responsible for getting the right format resolver for a given type
/// </summary>
public class FormatterResolver
{
private ObjectPropertyFormatter _objectPropertyFormatter;
private Dictionary<Type, object> _registeredFormatters;
public FormatterResolver()
{
_registeredFormatters = new Dictionary<Type, object>();
_objectPropertyFormatter = new ObjectPropertyFormatter();
}
public void RegisterFormatter<T>(IPropertyFormatter<T> formatter)
{
_registeredFormatters.Add(typeof(T), formatter);
}
public Func<string> GetFormatterFunc<T>(T value)
{
object formatter;
if (_registeredFormatters.TryGetValue(typeof(T), out formatter))
{
return () => (formatter as IPropertyFormatter<T>).FormatValue(value);
}
else
return () => ( _objectPropertyFormatter.FormatValue(value));
}
}
. Вам понадобится где-нибудь сохранить экземпляр formatResolver и зарегистрировать все средства форматирования.
public FormatterResolver _formatResolver;
public void RegisterFormatResolvers()
{
_formatResolver = new FormatterResolver();
_formatResolver.RegisterFormatter(new BoolPropertyFormatter());
_formatResolver.RegisterFormatter(new DateTimePropertyFormatter());
//...etc
}
Ваш метод будет выглядеть примерно так:
public string GetFormattedAttribute<T>(T propertyValue)
{
return _formatResolver.GetFormatterFunc(propertyValue)();
}
Итак, время проверить его, все ли работает?Это быстрый тест на исправность, который показывает, что приведенный выше код работает должным образом.
[TestMethod]
public void TestFormatResolvers()
{
RegisterFormatResolvers();
Assert.AreEqual("yeaaah", GetFormattedAttribute(true));
Assert.AreEqual("nope", GetFormattedAttribute(false));
Assert.AreEqual("<b>20120120</b>", GetFormattedAttribute(new DateTime(2012, 01, 20)));
Assert.AreEqual("5", GetFormattedAttribute(5));
}
Если ваша логика форматирования также зависит от propertyName, все, что вам нужно сделать, это изменить интерфейс на:
public interface IPropertyFormatter<T> {
string FormatValue(string propertyName, T value);
}
и соответственно реализовать классы-потомки