c# - डब्ल्यूसीएफ चैनल फैक्टरी<टी> बनाना




.net wcf (3)

@NelsonRothermel, हाँ, मैं चैनलफैक्टरी प्रबंधक चैनलफॉल्टेड ईवेंट हैंडलर में एक कोशिश पकड़ने का उपयोग न करने की सड़क पर चला गया। तो चैनलफॉल्ट बन जाएगा

 private void ChannelFaulted(object sender, EventArgs e)
    {
        IClientChannel channel = (IClientChannel)sender;            
        channel.Abort();
    }

लगता है कि मूल अपवाद को बुलबुला करने की अनुमति है। चैनल.क्लोज़ का उपयोग न करने का भी चयन किया क्योंकि यह एक अपवाद फेंकने लगता है क्योंकि चैनल पहले से ही एक दोषपूर्ण स्थिति में है। फैक्ट्रीफॉल्टेड ईवेंट हैंडलर के समान समस्याएं हो सकती हैं। बीटीडब्ल्यू @ डारिन, कोड का अच्छा सा ...

मैं मौजूदा .NET रिमोटिंग एप्लिकेशन को डब्ल्यूसीएफ में बदलने की कोशिश कर रहा हूं। सर्वर और क्लाइंट दोनों साझा इंटरफेस साझा करते हैं और सभी ऑब्जेक्ट्स सर्वर-सक्रिय ऑब्जेक्ट्स हैं।

डब्ल्यूसीएफ दुनिया में, यह प्रति-कॉल सेवा बनाने और प्रॉक्सी बनाने के लिए ChannelFactory<T> का उपयोग करने जैसा ही होगा। मैं एक एएसपी.NET क्लाइंट के लिए ChannelFactory<T> को सही ढंग से बनाने के तरीके के साथ थोड़ा संघर्ष कर रहा हूं।

प्रदर्शन कारणों से, मैं ChannelFactory<T> ऑब्जेक्ट्स को कैश करना चाहता हूं और हर बार जब मैं सेवा कहता हूं तो चैनल बना सकता हूं। .NET रिमोटिंग दिनों में, क्लाइंट ऑब्जेक्ट्स का संग्रह प्राप्त करने के लिए RemotingConfiguration.GetRegisteredWellknownClientTypes() विधि का उपयोग किया जाता था जिसे मैं कैश कर सकता था। ऐसा लगता है, डब्ल्यूसीएफ दुनिया में ऐसी कोई बात नहीं है, हालांकि मैं कॉन्फ़िगरेशन फ़ाइल से एंडपॉइंट्स का संग्रह प्राप्त करने में सक्षम था।

अब यह है कि मुझे लगता है कि काम करेगा। मैं ऐसा कुछ बना सकता हूं:

public static ProxyHelper
{
    static Dictionary<Type, object> lookup = new Dictionary<string, object>();  

    static public T GetChannel<T>()
    {
        Type type = typeof(T);
        ChannelFactory<T> factory;

        if (!lookup.ContainsKey(type))
        {
            factory = new ChannelFactory<T>();
            lookup.Add(type, factory);
        }
        else
        {
            factory = (ChannelFactory<T>)lookup[type];
        }

        T proxy = factory.CreateChannel();   
        ((IClientChannel)proxy).Open();

        return proxy;
    }    
}

मुझे लगता है कि उपर्युक्त कोड काम करेगा, लेकिन अगर मैं लुकअप में नहीं हूं तो नए ChannelFactory<T> ऑब्जेक्ट्स जोड़ने की कोशिश कर रहे कई धागे के बारे में मैं थोड़ा चिंतित हूं। चूंकि मैं .NET 4.0 का उपयोग कर रहा हूं, इसलिए मैं ConcurrentDictionary का उपयोग करने के बारे में सोच रहा था और GetOrAdd() विधि का उपयोग कर रहा TryGetValue() या TryGetValue() विधि का उपयोग पहले यह जांचने के लिए करता GetOrAdd() ChannelFactory<T> मौजूद है और यह अस्तित्व में नहीं है, फिर GetOrAdd() विधि का उपयोग करें। ConcurrentDictionary.TryGetValue() और ConcurrentDictionary.GetOrAdd() विधि के प्रदर्शन के बारे में निश्चित नहीं है।

एक अन्य मामूली सवाल यह है कि क्या मुझे ASP.NET एप्लिकेशन समाप्त होने के बाद चैनल फैक्ट्री ऑब्जेक्ट्स पर ChannelFactory.Close() विधि को कॉल करने की आवश्यकता है या क्या मैं सिर्फ .NET फ्रेमवर्क को चैनल फैक्ट्री ऑब्जेक्ट्स को स्वयं ही निपटाने देता हूं। ((IChannel)proxy).Close() का उपयोग करके सेवा विधि को कॉल करने के बाद प्रॉक्सी चैनल हमेशा बंद हो जाएगा ((IChannel)proxy).Close()((IChannel)proxy).Close() विधि।


मुझे कॉलिंग निर्माण पसंद नहीं आया:

WCFServiceInvoker invoker = new WCFServiceInvoker();
var result = invoker.InvokeService<IClaimsService, ICollection<string>>(proxy => proxy.GetStringClaims());

इसके अलावा आप एक ही चैनल का दो बार उपयोग नहीं कर सकते हैं।

मैंने यह समाधान बनाया है:

using(var i = Connection<IClaimsService>.Instance)
{           
   var result = i.Channel.GetStringClaims();
}

अब आप उसी चैनल का पुन: उपयोग कर सकते हैं जब तक कि कथन का उपयोग निपटान को न कहें।

GetChannel विधि मूल रूप से एक चैनलफैक्टरी है। CreateChannel () कुछ अतिरिक्त कॉन्फ़िगरेशन के साथ मैं उपयोग कर रहा हूं।

आप चैनलफैक्टरी के लिए कुछ कैशिंग बना सकते हैं क्योंकि अन्य समाधान करते हैं।

कनेक्शन वर्ग के लिए कोड:

public static class Connection<T>
   {
      public static ChannelHolder Instance
      {
         get
         {
            return new ChannelHolder();
         }
      }

      public class ChannelHolder : IDisposable
      {
         public T Channel { get; set; }

         public ChannelHolder()
         {
            this.Channel = GetChannel();
         }

         public void Dispose()
         {
            IChannel connection = null;
            try
            {
               connection = (IChannel)Channel;
               connection.Close();
            }
            catch (Exception)
            {
               if (connection != null)
               {
                  connection.Abort();
               }
            }
         }
      }
}

हां, अगर आप ऐसा कुछ बनाना चाहते हैं - उन सभी ChannelFactory<T> उदाहरणों को पकड़ने के लिए एक स्थिर वर्ग - आपको निश्चित रूप से यह सुनिश्चित करना होगा कि यह वर्ग 100% थ्रेड-सुरक्षित है और समवर्ती रूप से पहुंचने पर ठोकर नहीं खा सकता है। मैंने अभी तक .NET 4 की विशेषताओं का उपयोग नहीं किया है, इसलिए मैं उन पर विशेष रूप से टिप्पणी नहीं कर सकता - लेकिन मैं निश्चित रूप से इसे यथासंभव सुरक्षित बनाने की अनुशंसा करता हूं।

आपके दूसरे (नाबालिग) प्रश्न के लिए: चैनलफैक्टरी स्वयं एक स्थिर वर्ग है - इसलिए आप वास्तव में एक .Close() विधि को कॉल नहीं कर सकते हैं। यदि आप पूछना चाहते थे कि वास्तविक IChannel पर IChannel .Close() विधि को कॉल करना है या नहीं, तो फिर: हाँ, एक अच्छा नागरिक बनने के लिए अपना सर्वश्रेष्ठ प्रयास करें और यदि आप कभी भी कर सकते हैं तो उन चैनलों को बंद करें। यदि आप एक को याद करते हैं, तो .NET इसका ख्याल रखेगा - लेकिन अपने अप्रयुक्त चैनलों को फर्श पर टॉस न करें और आगे बढ़ें - अपने आप को साफ करें! :-)





channelfactory