जिस परियोजना पर मैं काम कर रहा हूं उसके पास डोमेन मॉडल में बड़ी संख्या में मुद्रा गुण हैं और मुझे इन्हें देखने के लिए प्रेषण के लिए $#,###.##
के रूप में प्रारूपित करने की आवश्यकता है। मेरे पास अलग-अलग दृष्टिकोणों के रूप में विचार विचार हैं जिनका उपयोग किया जा सकता है। एक दृष्टिकोण दृश्य के अंदर स्पष्ट रूप से मान स्वरूपित करने के लिए, "Pattern 1" from Steve Michelotti में के रूप में हो सकता है:कस्टम प्रारूपण के साथ एएसपी.नेट एमवीसी व्यू मॉडेल मैपिंग
... लेकिन यह बहुत जल्दी DRY principle का उल्लंघन करने शुरू होता है।
पसंदीदा दृष्टिकोण डोमेनमोडेल और व्यूमोडेल के बीच मैपिंग के दौरान प्रारूपण करना प्रतीत होता है (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
के साथ स्पष्ट रूप से परिभाषित करने की आवश्यकता नहीं है क्योंकि गुणों का नाम समान है - क्या कोई बेहतर है इस मैपिंग को परिभाषित करने का तरीका? जैसा कि मैंने उल्लेख किया है, मुद्रा मूल्यों के साथ बहुत अच्छी संपत्तियां हैं जिन्हें इस फैशन में मैप करने की आवश्यकता होगी।
कहा जा रहा है - क्या एक तरीका है कि मैं इन मैपिंगों को विश्व स्तर पर कुछ नियमों को परिभाषित करके स्वचालित रूप से हल कर सकता हूं? 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>()
... ताकि मैं प्रत्येक के लिए बॉयलरप्लेट सेटअप की मात्रा को कम कर सकते हैं ऑब्जेक्ट प्रकार
मुझे दृश्य से कस्टम स्वरूपण को पूरा करने के लिए किसी भी वैकल्पिक रणनीति की सुनवाई में भी रूचि है।
पहले तो हम सीधे देखने के लिए इस सरल वस्तु है, लेकिन दिनांक समय पारित करने के लिए परीक्षा हो सकती है? गुण [मॉडल में] समस्याएं पैदा करेगा। उदाहरण के लिए, हमें उनके लिए स्वरूपण जैसे ToShortDateString() या ToString() चुनने की आवश्यकता है। व्यू को को से स्क्रीन को रखने के लिए शून्य होने पर स्क्रीन को रखने के लिए जांच करने के लिए मजबूर किया जाएगा। दृश्य परीक्षण के लिए दृश्य कठिन हैं, इसलिए हम उन्हें जितना संभव हो पतला रखना चाहते हैं।क्योंकि व्यू का आउटपुट प्रतिक्रिया स्ट्रीम को पारित एक स्ट्रिंग है, हम केवल ऑब्जेक्ट्स का उपयोग करेंगे जो स्ट्रिंगफ़्रेंडली हैं; कि , ऑब्जेक्ट्स जो कभी भी विफल नहीं होंगे जब ToString() उन पर कॉल किया जाता है। कॉन्फ़्रेंसफ़ॉर्म दृश्य मॉडल ऑब्जेक्ट इसका उदाहरण है। 4.14 सूचीबद्ध करने में नोटिस कि सभी गुण स्ट्रिंग हैं। इस दृश्य मॉडल ऑब्जेक्ट को देखने के डेटा में रखे जाने से पहले हमारे पास दिनांक स्वरूपित होंगे। यह तरीका, दृश्य को ऑब्जेक्ट पर विचार करने की आवश्यकता नहीं है, और यह जानकारी को ठीक से प्रारूपित कर सकता है।
<% = string.Format ("{0: c}", Model.CurrencyProperty)%> मुझे सुंदर लग रहा है। शायद मैं इसका उपयोग कर रहा हूं ... –