नाडर की तरह, शायद अधिक ढीला-युग्मित डिज़ाइन बनाने के बारे में सोचें। हालांकि, मेरे मामले में, ढीला-युग्मन उचित नहीं था। यहां मेरी कक्षा पदानुक्रम है, और कस्टम सीरियलाइजेशन या डीटीओ का उपयोग किये बिना मैं समस्या को हल करने का प्रस्ताव कैसे करता हूं।
मेरी प्रोजेक्ट में, मैं एक XML दस्तावेज़ के टुकड़ों का प्रतिनिधित्व करने के लिए ऑब्जेक्ट्स का एक पूरा समूह बना रहा हूं जो एक वेब सेवा के माध्यम से सबमिट किया जाएगा। बहुत बड़ी संख्या में टुकड़े हैं। सभी को हर अनुरोध के साथ नहीं भेजा जाता है (असल में, इस उदाहरण में, मैं एक प्रतिक्रिया मॉडलिंग कर रहा हूं, लेकिन अवधारणाएं समान हैं)। इन टुकड़ों का उपयोग अनुरोध को इकट्ठा करने के लिए ब्लॉक बनाने की तरह किया जाता है (या इस मामले में प्रतिक्रिया को अलग करना)। तो विरासत पदानुक्रम के बावजूद वांछित क्रम को पूरा करने के लिए एकत्रीकरण/encapsulation का उपयोग करने का एक उदाहरण यहां दिया गया है।
[Serializable]
public abstract class ElementBase
{
// This constructor sets up the default namespace for all of my objects. Every
// Xml Element class will inherit from this class.
internal ElementBase()
{
this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
new XmlQualifiedName(string.Empty, "urn:my-default-namespace:XSD:1")
});
}
[XmlNamespacesDeclaration]
public XmlSerializerNamespaces Namespaces { get { return this._namespaces; } }
private XmlSerializationNamespaces _namespaces;
}
[Serializable]
public abstract class ServiceBase : ElementBase
{
private ServiceBase() { }
public ServiceBase(Guid requestId, Guid? asyncRequestId = null, Identifier name = null)
{
this._requestId = requestId;
this._asyncRequestId = asyncRequestId;
this._name = name;
}
public Guid RequestId
{
get { return this._requestId; }
set { this._requestId = value; }
}
private Guid _requestId;
public Guid? AsyncRequestId
{
get { return this._asyncRequestId; }
set { this._asyncRequestId = value; }
}
private Guid? _asyncRequestId;
public bool AsyncRequestIdSpecified
{
get { return this._asyncRequestId == null && this._asyncRequestId.HasValue; }
set { /* XmlSerializer requires both a getter and a setter.*/ ; }
}
public Identifier Name
{
get { return this._name; }
set { this._name; }
}
private Identifier _name;
}
[Serializable]
public abstract class ServiceResponseBase : ServiceBase
{
private ServiceBase _serviceBase;
private ServiceResponseBase() { }
public ServiceResponseBase(Guid requestId, Guid? asyncRequestId = null, Identifier name = null, Status status = null)
{
this._serviceBase = new ServiceBase(requestId, asyncRequestId, name);
this._status = status;
}
public Guid RequestId
{
get { return this._serviceBase.RequestId; }
set { this._serviceBase.RequestId = value; }
}
public Guid? AsyncRequestId
{
get { return this._serviceBase.AsyncRequestId; }
set { this._serviceBase.AsyncRequestId = value; }
}
public bool AsynceRequestIdSpecified
{
get { return this._serviceBase.AsyncRequestIdSpecified; }
set { ; }
}
public Identifier Name
{
get { return this._serviceBase.Name; }
set { this._serviceBase.Name = value; }
}
public Status Status
{
get { return this._status; }
set { this._status = value; }
}
}
[Serializable]
[XmlRoot(Namespace = "urn:my-default-namespace:XSD:1")]
public class BankServiceResponse : ServiceResponseBase
{
// Determines if the class is being deserialized.
private bool _isDeserializing;
private ServiceResponseBase _serviceResponseBase;
// Constructor used by XmlSerializer.
// This is special because I require a non-null List<T> of items later on.
private BankServiceResponse()
{
this._isDeserializing = true;
this._serviceResponseBase = new ServiceResponseBase();
}
// Constructor used for unit testing
internal BankServiceResponse(bool isDeserializing = false)
{
this._isDeserializing = isDeserializing;
this._serviceResponseBase = new ServiceResponseBase();
}
public BankServiceResponse(Guid requestId, List<BankResponse> responses, Guid? asyncRequestId = null, Identifier name = null, Status status = null)
{
if (responses == null || responses.Count == 0)
throw new ArgumentNullException("The list cannot be null or empty", "responses");
this._serviceResponseBase = new ServiceResponseBase(requestId, asyncRequestId, name, status);
this._responses = responses;
}
[XmlElement(Order = 1)]
public Status Status
{
get { return this._serviceResponseBase.Status; }
set { this._serviceResponseBase.Status = value; }
}
[XmlElement(Order = 2)]
public Guid RequestId
{
get { return this._serviceResponseBase.RequestId; }
set { this._serviceResponseBase.RequestId = value; }
}
[XmlElement(Order = 3)]
public Guid? AsyncRequestId
{
get { return this._serviceResponseBase.AsyncRequestId; }
set { this._serviceResponseBase.AsyncRequestId = value; }
}
[XmlIgnore]
public bool AsyncRequestIdSpecified
{
get { return this._serviceResponseBase.AsyncRequestIdSpecified; }
set { ; } // Must have this for XmlSerializer.
}
[XmlElement(Order = 4)]
public Identifer Name
{
get { return this._serviceResponseBase.Name; }
set { this._serviceResponseBase.Name; }
}
[XmlElement(Order = 5)]
public List<BankResponse> Responses
{
get { return this._responses; }
set
{
if (this._isDeserializing && this._responses != null && this._responses.Count > 0)
this._isDeserializing = false;
if (!this._isDeserializing && (value == null || value.Count == 0))
throw new ArgumentNullException("List cannot be null or empty.", "value");
this._responses = value;
}
}
private List<BankResponse> _responses;
}
तो, जबकि मैं निहित वर्गों के सभी के लिए गुण पैदा करने के लिए है, मैं मैं निहित वर्ग (ते) संपत्ति setters/टिककर खेल के भीतर हो सकता है किसी भी कस्टम तर्क बस निहित वर्ग के गुणों का उपयोग करते समय से प्रतिनिधि कर सकते हैं पत्ती वर्ग की संपत्तियों का उपयोग किया जाता है। चूंकि कोई विरासत नहीं है, इसलिए मैं XmlElementAttribute
विशेषता के साथ पत्ती वर्ग के सभी गुणों को सजाने और किसी भी ऑर्डरिंग का उपयोग कर सकता हूं जो मैं फिट देखता हूं।
अद्यतन:
मैं वापस आया इस लेख फिर से क्योंकि वर्ग वंशानुक्रम का उपयोग के बारे में मेरे डिजाइन फैसले वापस मुझे फिर से काटने के लिए आया था। जबकि उपरोक्त मेरा समाधान काम करता है, मैं इसका उपयोग कर रहा हूं, मुझे सच में लगता है कि नाडर का समाधान सबसे अच्छा है और मैंने प्रस्तुत किए गए समाधान से पहले विचार किया जाना चाहिए। असल में, मैं आज उसे +1 कर रहा हूं! मुझे वास्तव में उसका जवाब पसंद है, और यदि मेरे पास कभी भी मेरी वर्तमान परियोजना को दोबारा करने का अवसर है, तो मैं निश्चित रूप से ऑब्जेक्ट्स के लिए क्रमबद्ध तर्क से व्यवसाय ऑब्जेक्ट को अलग कर दूंगा जो अन्यथा कोड को सरल बनाने और इसे आसान बनाने के लिए विरासत से बहुत लाभान्वित होगा दूसरों के उपयोग और समझने के लिए।
आपकी प्रतिक्रिया नाडर पोस्ट करने के लिए धन्यवाद, क्योंकि मुझे लगता है कि कई इसे बहुत ही निर्देशक और उपयोगी पाएंगे।
मुझे इस तरह की समस्या थी जहां मुझे एसओएपी संदेश में अंतिम बार दिखाई देने के लिए व्युत्पन्न कक्षा में संपत्ति की आवश्यकता थी, मेरा समाधान बेस क्लास में संपत्ति को आंतरिक रूप से जोड़ना था, फिर इसे "नया" कीवर्ड से छुपाएं व्युत्पन्न कक्षा में। मेरा जवाब देखें [यहां] (http://stackoverflow.com/questions/22174311/wcf-serialization-order-issue/22177272#22177272)। आशा करता हूँ की ये काम करेगा। –