{"id":29,"date":"2005-06-16T21:19:58","date_gmt":"2005-06-17T04:19:58","guid":{"rendered":"http:\/\/kennyw.com\/indigo\/29"},"modified":"2005-06-16T21:19:58","modified_gmt":"2005-06-17T04:19:58","slug":"channels-110a-ichannelfactory","status":"publish","type":"post","link":"https:\/\/kennyw.com\/?p=29","title":{"rendered":"Channels 110a: IChannelFactory"},"content":{"rendered":"<p>Sorry for the radio silence, I was on holiday in Alaska.  Now I&#8217;m back with extra vigor to continue our evolving tutorial. \ud83d\ude42<\/p>\n<p><em>NOTE: Source code for all of the files and functionality referenced in the next few posts is <a href=\"\/wp-content\/indigo\/UdpSample.zip\">available here.<\/a><\/em><\/p>\n<p>At the root of a custom transport implementation is the creation of your channels.  The channel layer uses a factory pattern for constructing channels.  We are implementing the <a href=\"http:\/\/kennyw.com\/indigo\/13\">Datagram message exchange pattern<\/a>.  So our <code><a href=\"http:\/\/kennyw.com\/channelinterfaces#ichannelfactory\">IChannelFactory<\/a><\/code> (client\/proxy) will support creating <a href=\"http:\/\/kennyw.com\/channelinterfaces#ioutputchannel\">IOutputChannel<\/a>s and our <code><a href=\"http:\/\/kennyw.com\/channelinterfaces#ilistenerfactory\">IListenerFactory<\/a><\/code> (service) will support listening for <a href=\"http:\/\/kennyw.com\/channelinterfaces#iinputchannel\">IInputChannel<\/a>s.<\/p>\n<p>Only the factory classes need to be public, not the <a href=\"http:\/\/kennyw.com\/channelinterfaces#ichannel\">IChannel<\/a> and <a href=\"http:\/\/kennyw.com\/channelinterfaces#ilistener\">IListener<\/a> implementations that they generate.  Indigo provides some base class helpers for this process.<\/p>\n<ul>\n<li><code>CommunicationObject<\/code> is a base class that implements <a href=\"http:\/\/kennyw.com\/icommunicationobject\">ICommunicationObject<\/a> and enforces the <a href=\"http:\/\/kennyw.com\/indigo\/18\">common state machine<\/a>. <\/li>\n<p><\/p>\n<li><code>ChannelManagerBase(:CommunicationObject)<\/code> is a base class that implements IChannelManager and takes care of managing a collection of channels that are created (IChannelFactory) or accepted (IListenerFactory).  ChannelManagerBase works in conjunction with ChannelBase, which is a base class that implements <a href=\"http:\/\/kennyw.com\/channelinterfaces#ichannel\">IChannel<\/a>.<\/li>\n<p><\/p>\n<li><code>ChannelFactoryBase(:ChannelManagerBase)<\/code> is a base class that implements <a href=\"http:\/\/kennyw.com\/channelinterfaces#ichannelfactory\">IChannelFactory<\/a> and consolidates the myriad CreateChannel() overloads into a single OnCreateChannel() abstract method. It also handles the concept of an InnerChannelFactory.<\/li>\n<p><\/p>\n<li><code>ListenerFactoryBase(:ChannelManagerBase)<\/code> is a base class that implements <a href=\"http:\/\/kennyw.com\/channelinterfaces#ilistenerfactory\">IListenerFactory<\/a>.  It takes care of managing a collection of listeners that are created, and works in conjunction with <code>ListenerBase<\/code>, which is a base class that implements <a href=\"http:\/\/kennyw.com\/channelinterfaces#ilistener\">IListener<\/a>.  It also handles the concept of an InnerListenerFactory.<\/li>\n<\/ul>\n<p>In our <a href=\"\/wp-content\/indigo\/UdpSample.zip\">sample code<\/a>, the Factory implementations are contained in <em>UdpChannelFactory.cs<\/em> and <em>UdpListenerFactory.cs<\/em>.  The IChannel implementations are in <em>UdpOutputChannel.cs<\/em> and <em>UdpInputChannel.cs<\/em>.  The IListener implementation is in <em>UdpInputListener.cs<\/em>.    There are some implementation details of the factories (such as <code>IBufferManager<\/code> and <code>MessageEncoderFactory<\/code>) deserving of their own future topics.  For the moment I will simply note that these utilities are very helpful in managing serialized message buffers and performing conversions between Message and serialized byte arrays.<\/p>\n<h4>UdpChannelFactory<a name=\"udpchannelfactory\">&nbsp;<\/a><\/h4>\n<p>UdpChannelFactory derives from ChannelFactoryBase.  It overrides the following properties and methods to accomplish the bulk of its work:<\/p>\n<div class=\"code\"><code class=\"keyword\">public override<\/code> MessageVersion MessageVersion { <code class=\"keyword\">get<\/code>; } <\/div>\n<div class=\"indent1\">For our implementation we hardcode the Message Version to SOAP 1.2+WS-Addressing 1.0.<\/div>\n<p><\/p>\n<div class=\"code\"><code class=\"keyword\">public override string<\/code> Scheme { <code class=\"keyword\">get<\/code>; }<\/div>\n<div class=\"indent1\">For Udp we&#8217;ve chosen <code class=\"string\">\"soap.udp\"<\/code> as our addressing scheme. <\/div>\n<p><\/p>\n<div class=\"code\"><code class=\"keyword\">public override bool<\/code> CanCreateChannel&lt;TChannel&gt;()<\/div>\n<div class=\"indent1\">This is where we declare that we only support IOutputChannel.<\/div>\n<p><\/p>\n<div class=\"code\"><code class=\"keyword\">protected override<\/code> TChannel OnCreateChannel&lt;TChannel&gt;(EndpointAddress remoteAddress)<\/div>\n<div class=\"indent1\">This is where we create our channel implementation (UdpOutputChannel).<\/div>\n<p>We also override OnOpen() and OnClosed() so that we can setup and tear-down our IBufferManager at the appropriate points in the <a href=\"http:\/\/kennyw.com\/indigo\/18\">state machine<\/a>.<\/p>\n<h4>UdpOutputChannel<a name=\"udpoutputchannel\">&nbsp;<\/a><\/h4>\n<p>UdpOutputChannel is our internal implementation of <a href=\"http:\/\/kennyw.com\/channelinterfaces#ioutputchannel\">IOutputChannel<\/a>. In the constructor we validate our arguments and, based on the EndpointAddress passed in, construct a <a href=\"http:\/\/msdn.microsoft.com\/library\/default.asp?url=\/library\/en-us\/cpref\/html\/frlrfsystemnetendpointclasstopic.asp\">System.Net.EndPoint<\/a> for our destination .<br \/>\nIn our OnOpen() override we create the Socket that we will use for sending data to this EndPoint:<\/p>\n<div class=\"code\">\n<div class=\"indent1\">this.socket = new Socket(this.remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);<\/div>\n<\/div>\n<p>We have 2 places where we need to clean up the socket, as the Channel can close gracefully using Close(), or ungracefully using Abort(). In the Abort() case we want to ensure that our base method gets called, which is why it&#8217;s in a finally block:<\/p>\n<div class=\"code\">\n<div class=\"indent1\"><code class=\"keyword\">try<\/code><br \/>\n       {<\/p>\n<div class=\"indent1\"><code class=\"keyword\">this<\/code>.socket.Close(0);<\/div>\n<p>}<br \/>\n       <code class=\"keyword\">finally<\/code><br \/>\n       {<\/p>\n<div class=\"indent1\"><code class=\"keyword\">base<\/code>.OnAbort();<\/div>\n<p>}<\/p><\/div>\n<\/div>\n<p>For Close(), we simply cleanup the socket and call our base class (if this throws, the infrastructure will call Abort() to ensure our channel is cleaned up):<\/p>\n<div class=\"code\">\n<div class=\"indent1\"><code class=\"keyword\">this<\/code>.socket.Close();<br \/>\n      <code class=\"keyword\">base<\/code>.OnClose();<\/div>\n<\/div>\n<p>We then implement Send() and BeginSend()\/EndSend().  This breaks down into two main sections.  First we serialize the message into a byte array:<\/p>\n<div class=\"code\">\n<div class=\"indent1\">ArraySegment&lt;<code class=\"keyword\">byte<\/code>&gt; messageBuffer = EncodeMessage(message);<\/div>\n<\/div>\n<p>Then we send the resulting data on the wire:<\/p>\n<div class=\"code\">\n<div class=\"indent1\"><code class=\"keyword\">this<\/code>.socket.SendTo(messageBuffer.Array, messageBuffer.Offset, messageBuffer.Count, SocketFlags.None, <code class=\"keyword\">this<\/code>.remoteEndPoint);<\/div>\n<\/div>\n<p>At this point our Send() call has finished its transmission task and we have sent a UDP datagram containing a text encoding serialization of a SOAP message.  Next I will cover the IListenerFactory implementation to receive this message.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sorry for the radio silence, I was on holiday in Alaska. Now I&#8217;m back with extra vigor to continue our evolving tutorial. \ud83d\ude42 NOTE: Source code for all of the files and functionality referenced in the next few posts is available here. At the root of a custom transport implementation is the creation of your [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[],"class_list":["post-29","post","type-post","status-publish","format-standard","hentry","category-indigo"],"_links":{"self":[{"href":"https:\/\/kennyw.com\/index.php?rest_route=\/wp\/v2\/posts\/29","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kennyw.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kennyw.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kennyw.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/kennyw.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=29"}],"version-history":[{"count":0,"href":"https:\/\/kennyw.com\/index.php?rest_route=\/wp\/v2\/posts\/29\/revisions"}],"wp:attachment":[{"href":"https:\/\/kennyw.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=29"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kennyw.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=29"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kennyw.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=29"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}