The data contained in Channel FileData consists of the request URI ITransport Headers and the Stream

[Serializable]

public class ChannelFileData {

private String m_URI = null;

private ITransportHeaders m_Header = null;

private byte[] m_StreamBytes = null;

public ChannelFileData( String URI,

ITransportHeaders headers, Stream stream )

String objectURI;

String ChannelURI = FileChannelHelper.Parse( URL, out objectURI );

objectURI = URL;

m_URI = objectURI; m_Header = headers;

m_StreamBytes = new Byte[ (int)stream.Length ]; stream.Read( m_StreamBytes, 0, (int) stream.Length ); stream.Position = 0;

public String URI {

return m_URI;

public ITransportHeaders header {

return m_Header;

public Stream stream {

return new MemoryStream( m_StreamBytes, false );

First, notice that ChannelFileData has the Serializable attribute. This is integral for the next step. The only way to set data in ChannelFileData is through the constructor. To retrieve the data from the ChannelFileData object, we provide read-only properties.

Now that we have our data class to serialize, we need to create a class that writes the file to disk. This class, ChannelFileTransportWriter, will have a single method, named Write. For parameters, Write will take a ChannelFileData object, a path to write the file, and a name for the file.

public class ChannelFileTransportWriter {

private ChannelFileTransportWriter() {

public static String Write( ChannelFileData data,

String ServerPath, String FileName )

// If FileName is null, generate a filename with Guid.NewGuid if( FileName == null ) {

FileName = Path.Combine( ServerPath,

Guid.NewGuid().ToString() + ".chn.server" );

// Append _Temp to the file name so the file is not accessed // by the server or client before we are finished writing the // file. After the data is written, we will rename the file. String TempFileName = FileName + "_Temp"; IFormatter DataFormatter = new SoapFormatter(); Stream DataStream = new FileStream( TempFileName,

FileMode.Create, FileAccess.Write, FileShare.None ); DataFormatter.Serialize( DataStream, data); DataStream.Close();

File.Move( TempFileName, FileName ); return FileName;

ChannelFileTransportWriter has a few key items of note. First, ChannelFileTransportWriter maintains no state, so we don't need instances of this class. This allows us to make the constructor private and the Write method static. Notice that we use Guid.NewGuid to generate unique names. This allows us to avoid naming conflicts when we use multiple channels to connect to the server.

Now that we can write request and response message files, we must be able to read them. To do this, we'll create a class named ChannelFileTransportReader that defines a single method named Read that will populate a ChannelFileData object:

public class ChannelFileTransportReader {

private Channel FileTransportReader() {

public static ChannelFileData Read( String FileName ) {

IFormatter DataFormatter = new SoapFormatter(); Stream DataStream = new FileStream( FileName,

FileMode.Open,

FileAccess.Read,

FileShare.Read);

ChannelFileData data =

(ChannelFileData) DataFormatter.Deserialize(

DataStream );

DataStream.Close();

File.Move( FileName, FileName + "_processed" ); return data;

Notice in the Read method that, after we're finished with a message, we append the string _processed to the end of the filename. This allows us to see a history of the messages that were sent between the server and client.

The final transport class we need to create is WaitForFile. WaitForFile will have two methods, Wait and ¬°nfiniteWait. Wait's responsibility is to wait for some period for a file to appear.

public static bool Wait( String filename ) {

int RetryCount = 120;

Thread.Sleep( 500 );

return true;

RetryCount--;

return false;

Wait checks for the file every half second for 1 minute. A more advanced version of FileChannel would allow you to set the retry count and the sleep time in the configuration file. ¬°nfiniteWait will wake up every half a second to see whether a file with an extension of server is in the specified directory.

public static String InfiniteWait( String DirectoryToWatch ) {

// Loop forever or until a file is found.

String[] File = Directory.GetFiles( DirectoryToWatch,

return File[0];

Thread.Sleep( 500 );

0 0

Post a comment