Проект, над которым я работаю, имеет большое количество валютных свойств в модели домена, и мне нужно их форматировать как $#,###.##
для передачи в представление и из представления. У меня были мысли о различных подходах, которые можно было бы использовать. Один из подходов может быть форматировать значения явно внутри вида, как и в "Pattern 1" from Steve Michelotti:ASP.NET MVC сопоставление ViewModel с пользовательским форматированием
... но это начинает нарушать DRY principle очень быстро.
Предпочитаемый подход заключается в том, чтобы делать форматирование во время сопоставления между DomainModel и ViewModel (согласно ASP.NET MVC in Action, раздел 4.4.1 и "Pattern 3"). Использование AutoMapper, это приведет к некоторому коду, как в следующем:
[TestFixture]
public class ViewModelTests
{
[Test]
public void DomainModelMapsToViewModel()
{
var domainModel = new DomainModel {CurrencyProperty = 19.95m};
var viewModel = new ViewModel(domainModel);
Assert.That(viewModel.CurrencyProperty, Is.EqualTo("$19.95"));
}
}
public class DomainModel
{
public decimal CurrencyProperty { get; set; }
}
public class ViewModel
{
///<summary>Currency Property - formatted as $#,###.##</summary>
public string CurrencyProperty { get; set; }
///<summary>Setup mapping between domain and view model</summary>
static ViewModel()
{
// map dm to vm
Mapper.CreateMap<DomainModel, ViewModel>()
.ForMember(vm => vm.CurrencyProperty, mc => mc.AddFormatter<CurrencyFormatter>());
}
/// <summary> Creates the view model from the domain model.</summary>
public ViewModel(DomainModel domainModel)
{
Mapper.Map(domainModel, this);
}
public ViewModel() { }
}
public class CurrencyFormatter : IValueFormatter
{
///<summary>Formats source value as currency</summary>
public string FormatValue(ResolutionContext context)
{
return string.Format(CultureInfo.CurrentCulture, "{0:c}", context.SourceValue);
}
}
Использование IValueFormatter
таким образом работает. Теперь, как отобразить его обратно из DomainModel в ViewModel? Я попытался с помощью настраиваемого class CurrencyResolver : ValueResolver<string,decimal>
public class CurrencyResolver : ValueResolver<string, decimal>
{
///<summary>Parses source value as currency</summary>
protected override decimal ResolveCore(string source)
{
return decimal.Parse(source, NumberStyles.Currency, CultureInfo.CurrentCulture);
}
}
А потом замэпили с:
// from vm to dm
Mapper.CreateMap<ViewModel, DomainModel>()
.ForMember(dm => dm.CurrencyProperty,
mc => mc
.ResolveUsing<CurrencyResolver>()
.FromMember(vm => vm.CurrencyProperty));
который удовлетворит этот тест:
///<summary>DomainModel maps to ViewModel</summary>
[Test]
public void ViewModelMapsToDomainModel()
{
var viewModel = new ViewModel {CurrencyProperty = "$19.95"};
var domainModel = new DomainModel();
Mapper.Map(viewModel, domainModel);
Assert.That(domainModel.CurrencyProperty, Is.EqualTo(19.95m));
}
... Но я чувствую, что Мне не нужно явно определять, к какому свойству он сопоставляется с FromMember
после выполнения ResolveUsing
, так как свойства имеют одно и то же имя - есть ли лучше способ определить это отображение? Как я уже упоминал, существует большое количество свойств с валютными ценностями, которые должны быть сопоставлены таким образом.
Это, как говорится, есть способ, которым я мог бы автоматически преобразовывать эти сопоставления, определяя какое-то правило глобально? Свойства ViewModel уже украшены DataAnnotation
атрибуты [DataType(DataType.Currency)]
для проверки, так что я надеялся, что я мог бы определить некоторые правила, что делает:
if (destinationProperty.PropertyInfo.Attributes.Has(DataType(DataType.Currency))
then Mapper.Use<CurrencyFormatter>()
if (sourceProperty.PropertyInfo.Attributes.Has(DataType(DataType.Currency))
then Mapper.Use<CurrencyResolver>()
... так что я могу свести к минимуму количества установки шаблонной для каждого из типы объектов.
Мне также интересно узнать о любых альтернативных стратегиях для выполнения пользовательского форматирования в представлении и из представления.
Сначала мы могли бы попытаться передать этот простой объект прямо к зрения, но DateTime? свойства [в модели] вызовут проблемы. Например, нам нужно выбрать форматирование , например ToShortDateString() или ToString(). Вид будет вынужден сделать нулевое значение , чтобы сохранить экран с взорвать, когда свойства null. Мнения сложны для измерения , поэтому мы хотим сохранить их как можно более тонкие .Поскольку вывод изображения представляет собой строку, переданную в ответный поток , мы будем использовать только объекты, которые являются строчными; что - это объекты, которые никогда не сбой, если на них вызывается ToString(). Объект модели ConferenceForm - пример этого примера . В листинге 4.14 указано, что все свойства являются строками. Мы будем иметь даты правильно отформатирован перед этим видом модели объект находится в поле зрения данных. Этот способ , вид не должен учитывать объект , и он может правильно отформатировать .
<% = string.Format ("{0: c}", Model.CurrencyProperty)%> выглядит симпатичным для меня. Может быть, я просто привык к этому ... –