2009-09-03 19 views
8

मेरे पास निम्न है:डब्ल्यूसीएफ: इंटरफेस, जेनरिक और सर्विसकनाउन टाइप

[ServiceContract] 
[ServiceKnownType(typeof(ActionParameters))] 
[ServiceKnownType(typeof(SportProgram))] 
[ServiceKnownType(typeof(ActionResult<SportProgram>))] 
public interface ISportProgramBl 
{ 
    [OperationContract] 
    IActionResult<ISportProgram> Get(IActionParameters parameters); 
} 

जब मैं गेट विधि चलाता हूं तो मुझे निम्न त्रुटि मिलती है:

There was an error while trying to serialize parameter http://tempuri.org/:GetResult. The InnerException message was 'Type 'PPS.Core.DomainModel.Support.Action.ActionResult`1[ [PPS.Core.DomainModel.SportProgram.ISportProgram, PPS.Core.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' with data contract name 'ActionResultOfanyType: http://schemas.datacontract.org/2004/07/PPS.Core.DomainModel.Support.Action' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.

इस त्रुटि से मैं देख सकता हूं कि यह ActionResult को हल कर सकता है लेकिन यह ISportProgram को हल नहीं कर सकता भले ही मेरे पास serviceKnownType (टाइपऑफ (एक्शन रिसेट < SportProgram>)) मेरे सेवा इंटरफ़ेस पर है ...

नोट यह संदर्भ स्टब है जो उत्पन्न होता है इस तरह दिखता है, इसलिए मैं देख सकता हूं कि ज्ञात प्रकार हैं सही ढंग से लाया गया:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")] 
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="SportProgramStb.ISportProgramBl")] 
public interface ISportProgramBl { 

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISportProgramBl/Get", ReplyAction="http://tempuri.org/ISportProgramBl/GetResponse")] 
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.SportProgram.SportProgram))] 
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionParameters))] 
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionResult<PPS.Core.DomainModel.SportProgram.SportProgram>))] 
    object Get(object parameters); 
} 

यह गलत क्यों हो रहा है ???? ध्यान दें कि यह डब्लूसीएफ सेवा के माध्यम से सही तरीके से हो रहा है ... लेकिन जब परिणाम लौटाया जाता है तो यह अपवाद फेंकता है।

आखिरकार ActionResult इस तरह दिखता है:

public interface IActionResult<T> 
{ 
    T Result { get; set; } 
} 

चीयर्स एंथनी

+0

'एक्शन रिसेट ' प्रकार ''Serializer' अपेक्षा 'ServiceKnownType' प्रकार से उपलब्ध 'ActionResult ' प्रकार से अलग है! – Lightman

उत्तर

15

ठीक है, मुझे लगता है कि यह एसओए बनाम ओओपी "प्रतिबाधा मेल नहीं है" का एक और मामला है। दोनों दुनिया काफी अलग हैं।

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

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

यह प्रभाव के बहुत सारे है:

  • कोई इंटरफेस - आप इंटरफेस के आसपास पारित नहीं कर सकते हैं - आप ठोस प्रकार के साथ काम करने की जरूरत
  • कोई "स्वचालित" विरासत - तुम सिर्फ एक आधार वर्ग और पास को परिभाषित नहीं कर सकते हैं चारों ओर उस पर आधारित कक्षाएं ली गई - फिर से, आप के बजाय ठोस प्रकार
उपयोग करने की आवश्यकता - उन भी specificied करने की आवश्यकता
  • कोई स्वचालित जेनरिक (कि क्या ServiceKnownType विशेषता के लिए है)

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

    तो मेरे पास वास्तव में आपके लिए कोई जवाब नहीं है - मुझे लगता है कि आपको अपनी रणनीति पर पुनर्विचार करने की आवश्यकता है और जिस तरह से आपका ग्राहक और सर्वर डब्ल्यूसीएफ पर जानकारी का आदान-प्रदान कर रहा है उसे बदल सकता है।

    मार्क

    पुनश्च: मैं कुछ और अधिक शोध किया है, और मेरे सभी समझ के विपरीत, वहाँ कुछ भी है कि एक इंटरफेस और/या तार के पार सार आधार वर्ग पर आधारित है क्रमानुसार करने के लिए एक रास्ता हो रहा है जब तक क्योंकि आप सुनिश्चित कर सकते हैं कि यह हमेशा तार के किसी भी छोर पर .NET है (यानी यह जावा के साथ इंटरऑपरेबल नहीं है)।

    Aaron Skonnard blog post on the NetDataContractSerializer देखें और एक अन्य blog post और yet another NetDataContractSerializer उपयोग करने के लिए कैसे अपने तरीकों के पैरामीटर के रूप में IPerson जैसी चीजों के आसपास पारित करने के लिए सक्षम होने के लिए दिखा।

  • +0

    मैं डब्ल्यूसीएफ को उन सभी संकेतों को देने के लिए तैयार हूं, लेकिन मैं इंटरफेस या जेनेरिक का उपयोग करने से नहीं बच सकता ... अगर किसी भी तरह से मैं इंटरफेस से छुटकारा पा सकता हूं तो क्या मैं अभी भी जेनिक्स का उपयोग कर सकता हूं ?? अगर मैं जेनेरिक से छुटकारा पा सकता हूं तो भी रिवर्स सच है क्या मैं अभी भी इंटरफेस का उपयोग कर सकता हूं ... मतलब यह है कि यह केवल 2 का संयोजन है जो मुझे समस्याएं पैदा कर रहा है ?? क्योंकि मैं IActionResult का अधिक विशिष्ट संस्करण बना सकता हूं जिसके लिए जेनेरिकों का उपयोग करने की आवश्यकता नहीं है ... –

    +0

    इस पोस्ट पर शोध करते समय मुझे मिली कुछ नई जानकारी के साथ मेरी पोस्ट अपडेट की गई - उम्मीद है कि इससे मदद मिलती है! –

    +0

    अद्यतन के लिए धन्यवाद ... मेरे मामले में NetDataContractSerializer बहुत अच्छा काम करता है ... –

    0

    आप वस्तुओं में इंटरफेस को निर्दिष्ट कर रहे हैं और नहीं ठोस प्रकार? (इंटरफेस के माध्यम से उप वस्तु में भी शामिल है)

    मैं क्या कह रहा हूँ है कि सभी ठोस प्रकार है कि आप जेनरिक में गुजर रहे हैं कर रहे हैं ज्ञात प्रकार सूची में पारित किया जा रहा:

    संपादित करें। हमारे पास धारावाहिक मुद्दे हैं जहां सभी प्रकार ज्ञात नहीं थे।

    +0

    आप से क्या मतलब है

    हालांकि, वहाँ कार्यान्वयन के साथ कुछ मुद्दों होने के लिए यहाँ उल्लेख किया लगता है उस? कॉन्सट्री ऑब्जेक्ट इंटरफ़ेस लागू करता है ... – vdhant

    0

    आप टी के एक आईएलिस्ट लौट रहे हैं। शायद यह है कि सिस्टम को यह पता लगाने में समस्याएं हैं कि टी क्या है।

    सुनिश्चित नहीं है कि किसी प्रकार के बजाय इंटरफ़ेस वापस करना ठीक है या नहीं।

    2

    यह उन समस्याओं में से एक है जिन्हें मैं ServiceStack.NET - मेरा ओपन सोर्स .NET और MONO वेब सेवा फ्रेमवर्क के साथ हल करता हूं।

    सर्विस स्टैक Martin Fowlers Data Transfer Object Pattern से काफी प्रभावित था क्योंकि यह आपको अपनी वेब सेवाओं को परिभाषित करने के लिए डीटीओ का उपयोग करने की अनुमति देता है - यानी एसओए रास्ता :)।

    मैं इस सीमा से बचता हूं जो डब्ल्यूसीएफ में अपना स्वयं का डब्लूएसडीएल उत्पन्न करके निहित है, जैसा कि आप उन्हें उम्मीद करेंगे। डब्ल्यूसीएफ के जटिल विन्यास/सर्विसकंट्रैक्ट के मॉडल को बदलने के लाभ के रूप में - एसओएपी वेब सेवाएं भी मोनो - see the live demo पर काम करती हैं।

    +0

    दिलचस्प लग रहा है लेकिन लाइव डेमो लिंक 404 है –

    1

    यह एक पुराना सवाल है और भले ही स्वीकृत उत्तर पूरी तरह से सही है, फिर भी मैंने इस तरह की एक समान समस्या की खोज में फंस लिया और सोचा कि मैं अपने अनुभव साझा कर सकता हूं। यह अक्सर सिरदर्द होता है, लेकिन डब्ल्यूसीएफ के साथ इंटरफेस के साथ संयुक्त जेनिक्स का उपयोग करना संभव है। यहाँ है कि मेरे द्वारा की गई एक और (समान) कार्यान्वयन की एक काम उदाहरण है:

    [ServiceContract] 
    [ServiceKnownType(typeof(CollectionWrapper<IAssociation>))] 
    public interface IService : 
    { 
        [OperationContract] 
        ICollectionWrapper<IAssociation> FindAssociation(string name, int pageSize, int page); 
    } 
    
    public interface ICollectionWrapper<TModel> 
    { 
        int TotalCount { get; set; } 
        IEnumerable<TModel> Items { get; set; } 
    } 
    
    [KnownType(typeof(OrganizationDto))] 
    [KnownType(typeof(CompanyDto))] 
    public class CollectionWrapper<TModel> : ICollectionWrapper<TModel> 
    { 
        [DataMember] 
        public int TotalCount { get; set; } 
        [DataMember] 
        public IEnumerable<TModel> Items { get; set; } 
    } 
    
    public class CompanyDto : IAssociation 
    { 
        public int Id { get; set; } 
        public string Name { get; set; } 
    } 
    
    public class OrganizationDto : IAssociation 
    { 
        public int Id { get; set; } 
        public string Name { get; set; } 
    } 
    

    कुंजी यहाँ KnownType और ServiceKnownType के संयोजन का उपयोग करें।

    तो आपके मामले में आप कुछ इस तरह कर सकते हैं:

    [ServiceContract] 
    [ServiceKnownType(typeof(ActionParameters))] 
    [ServiceKnownType(typeof(ActionResult<ISportProgram>))] // Actual implementation of container, but interface of generic. 
    public interface ISportProgramBl 
    { 
        [OperationContract] 
        IActionResult<ISportProgram> Get(IActionParameters parameters); 
    } 
    
    [KnownType(typeof(SportProgram))] // Actual implementation here. 
    public class ActionResult<T> 
    { 
        // Other stuff here 
        T FooModel { get; set; } 
    } 
    

    यदि आप एक साझा अनुबंध (वास्तविक सेवा इंटरफ़ेस के लिए उपयोग) है काम करेंगे और ChannelFactory<ISportProgramBl> के साथ अनुबंध खपत करते हैं। मुझे नहीं पता कि यह सेवा-संदर्भ के साथ काम करता है या नहीं।

    WCF With a interface and a generic model

    और एक और समान प्रश्न पूछा और यहां उत्तर:

    Generic return types with interface type params in WCF

    संबंधित मुद्दे