2010-07-26 11 views
6

मैं एक सेवा अनुबंध को लागू करने की कोशिश कर रहा हूं जिसमें एक सामान्य इंटरफेस लेता है, और जेनेरिक इंटरफ़ेस को एक इंटरफ़ेस पैरामीटर दिया जाता है। मैं ServiceKnownType साथ सेवा इंटरफ़ेस सजाया गया है, मैं नियमित रूप से KnownType साथ सेवा कार्यान्वयन सजाया है, और मैं नियमित रूप से KnownType साथ datacontract कार्यान्वयन सजाया हैडब्ल्यूसीएफ: क्या सामान्य जेनेरिक इंटरफेस का क्रमिकरण संभव है?

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ICallbacks))] 
[ServiceKnownType(typeof(Batch<object>))] 
[ServiceKnownType(typeof(Command))] 
public interface IActions 
{ 
    [OperationContract] 
    IResponse TakeAction(IBatch<ICommand> commands); 
} 

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant)] 
[KnownType(typeof(Batch<object>))] 
[KnownType(typeof(Command))] 
internal class Actions : IActions 
{ 
} 

[DataContract] 
[KnownType(typeof(Command))] 
public class Batch<T> : IBatch<T> 
{ 
} 

रिकॉर्ड के लिए, मैं बैच वहाँ है, क्योंकि ऐसा लगता है कि आप केवल एक सामान्य प्रकार के लिए एक ज्ञात टाइप व्यक्त कर सकते हैं - ऐसा लगता है कि यह बैचऑफनी टाइप को उत्सर्जित करता है, लेकिन मुझे यकीन नहीं है कि इसे कैसे संभाला जाए।

अपवाद रहा है हो रही है "ज्ञात प्रकारों की सूची को स्थिर नहीं जाना जाता है किसी भी प्रकार जोड़ें -। उदाहरण के लिए, KnownTypeAttribute विशेषता का उपयोग करके या उन्हें DataContractSerializer के लिए पारित ज्ञात प्रकारों की सूची में शामिल करके"

क्या कुछ स्पष्ट है कि मैं गलत कर रहा हूं? इंटरफेस के जेनेरिक इंटरफेस सिर्फ समर्थित नहीं हैं? रिकॉर्ड के लिए मैं इस परियोजना के लिए सी # 2.0 और .NET 3.0 पर हूं।

उत्तर

12

यदि आप वास्तव में चाहते हैं, तो आप सेवा अनुबंध परिभाषाओं में इंटरफेस का उपयोग कर सकते हैं, जब तक आप ज्ञात प्रकारों को शामिल कर रहे हों (थोड़ी सी समायोजन के साथ, नीचे देखें)।

जाहिर है, जेनेरिक टाइप पैरामीटर के रूप में एक इंटरफ़ेस का उपयोग करके इसे सी # 3.0 के लिए बहुत दूर एक पुल ले रहा है। मैंने ज्ञात प्रकार की विशेषता

[ServiceKnownType(typeof(Batch<Command>))] 
public interface IActions 
{ 
} 

जो इसे एक बिंदु पर काम करती है। क्रमबद्धता और अक्रमांकन ही काम करेंगे, लेकिन उसके बाद आप इस अपवाद के साथ सामना कर रहे हैं:

प्रकार की वस्तु कास्ट करने के लिए 'Batch`1 [कमान]' टाइप करने के लिए 'IBatch`1 [ICommand]' में असमर्थ।

उस कलाकार के लिए काम करने के लिए, आपको सामान्य प्रकार के covariance के लिए भाषा समर्थन की आवश्यकता है, जो कुछ सी # 4.0 में पेश किया गया है। यह हालांकि में काम करने के लिए सी # 4.0, आप एक विचरण संशोधक जोड़ने के पूरे करने होंगे:

public interface IBatch<out T> 
{ 
} 

तो यह पूरी तरह से काम करता है ... दुर्भाग्य से आप उपयोग नहीं कर रहे सी # 4.0।

आपके सेवा अनुबंध में इंटरफेस का उपयोग करने के बारे में एक आखिरी बात: यदि आप उनसे एक सेवा संदर्भ उत्पन्न कर रहे हैं, तो यह सभी इंटरफ़ेस पैरामीटर object के रूप में टाइप करेगा, क्योंकि मूल इंटरफ़ेस प्रकार मेटाडेटा का हिस्सा नहीं है। आप एक असेंबली संदर्भ के माध्यम से अनुबंध साझा कर सकते हैं, या इसे ठीक करने के लिए उत्पन्न प्रॉक्सी को मैन्युअल रूप से रीफैक्टर कर सकते हैं, लेकिन सभी में, डब्ल्यूसीएफ के साथ इंटरफेस का उपयोग करना संभवतः इसके लायक से अधिक परेशानी है।

+0

हाँ, मैंने उस मंच में संपादित किया है जिसका उपयोग मैं कर रहा हूं जब मैंने सी # 4.0 में कॉन्वर्सिस के बारे में सोचा था। ओह, अपग्रेड करने के लिए। – bwerks

2

डब्ल्यूसीएफ एक एसओए संदेश-आधारित प्रणाली है - यह सीरियलाइज्ड एक्सएमएल प्रारूप में तार में कुछ भी भेज सकता है जिसे एक्सएमएल स्कीमा में व्यक्त किया जा सकता है।

दुर्भाग्यवश, एक्सएमएल स्कीमा कुछ भी नहीं जानता है न तो इंटरफेस और न ही जेनेरिक, इसलिए नहीं - आप सामान्य रूप से उनको क्रमबद्ध नहीं कर सकते - आपको ठोस प्रकारों का उपयोग करने की आवश्यकता है।

+0

WCF उन्हें क्रमानुसार करने के लिए पर्याप्त जेनरिक समझ में करता है (मैं इसे किया है)। इंटरफेस पर आपका बिंदु सही है। – RQDQ

+0

@RQDQ क्या आपके पास यह दिखाने के लिए कोई जगह है? एक ब्लॉग, कोडप्रोजेक्ट आलेख या कुछ? यह देखने के लिए प्यार है! –

+1

@RQDQ: वास्तव में, यह पूरी तरह से सही नहीं है, आईएमओ। जबकि इंटरफ़ेस को क्रमबद्ध नहीं किया जा सकता है, कंक्रीट प्रकार का उपयोग किया जा सकता है * हो सकता है। 'मुश्किल' हिस्सा deserialization है, क्योंकि यह जानना आवश्यक है कि कौन सा ठोस प्रकार तत्काल करने के लिए। हालांकि, धारावाहिक डेटा में पर्याप्त जानकारी को ठीक करने के लिए शामिल किया गया है। – Thorarin

1

आप एक इंटरफेस को क्रमबद्ध नहीं कर सकते हैं। एक इंटरफ़ेस केवल ऑब्जेक्ट को अनुबंध को परिभाषित करता है। मुझे लगता है कि इसके लिए एक अपवाद ISerializable इंटरफ़ेस है।

+1

जब आप "ISERializable' serializing" हैं, तो आप वास्तव में नहीं हैं। 'ISerializable' एक इंटरफ़ेस है जो किसी और चीज को क्रमबद्ध करने के लिए उपयोग किया जाता है। –

+0

@ जॉन। तुम सही हो। आप अभी भी इंटरफ़ेस को क्रमबद्ध नहीं कर रहे हैं, केवल उन वस्तुओं को क्रमबद्ध करने के लिए उपयोग किए गए अनुबंध पर सहमत हैं जो ISerializable लागू करते हैं। मैंने इसे पूर्णता के लिए जोड़ा है। – Mike

1

जेनिक्स को क्रमबद्ध किया जा सकता है, लेकिन कुछ सीमाओं के साथ।

[DataContract] 
public class Foo<T> 
{ 
    [DataMember] 
    public T Value { get; set; } 
} 

और सेवा अनुबंध:

[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    Foo<String> GetData(); 
} 

और सेवा कार्यान्वयन:

public class Service1 : IService1 
{ 
    public Foo<string> GetData() 
    { 
     return new Foo<string>() { Value = "My test string" }; 
    } 
} 

ऊपर सेवा करने के लिए एक सेवा संदर्भ स्थापित करने के बाद, इस उदाहरण के लिए, डेटा अनुबंध दिया कोड चलाया जा सकता है:

ServiceReference1.Service1Client client = new ServiceReference1.Service1Client(); 

ServiceReference1.FooOfstring temp = client.GetData(); 

MessageBox.Show(temp.Value); 

और "मेरा परीक्षण स्ट्रिंग" वाला संदेश बॉक्स प्रदर्शित होता है।

ध्यान दें कि सेवा स्वयं सामान्य नहीं है, लेकिन डेटा अनुबंध का उपयोग किया जाता है। इसके अलावा, डाटा क्लाइंट पक्ष पर उत्पन्न अनुबंध साधारण नहीं है, बल्कि एक "चपटा" वर्ग प्रकार स्ट्रिंग की संपत्ति मूल्य होता है:

[System.Runtime.Serialization.DataMemberAttribute()] 
public string Value 
{ 
    get {...} 
    set {...} 
} 
संबंधित मुद्दे