Client -III-

m104_sombrero

In my previous post, I started the implementation of WPF program entry point and the View <=> ViewModel interaction basics. The goal of this “Client chapter” is to get a client application which connects to the basic server application I covered earlier. This post continues the basic infrastructure where the Views and ViewModels become integrated.

So lets start with some auxiliary entities projects and than go to very essential internals with Interfaces project. I have only one project contain all interfaces for the entire solution and do the separation of concerns by their namespaces and for better overview make use of folders. But first lets care about some unobtrusive stuff:

Project “CoreSettings”

During startup the client application does some stuff automatically. For instance it checks whether there is already some client folder structure and creates it if not. Also it need to restore workspaces and other settings from an finished session during startup. For doing all this kind of tasks there is an project named CoreSettings.

This class controls all saving and loading actions. Its just the very basic implementation and it will be extended further in later chapters.

using System;
using System.IO;
using Client.Interfaces;

namespace Client.CoreSettings
{
    public class ControlCore : ICore
    {
        public IViewDispatcher ViewDispatcher { get; set; }
        public IFolderManager FolderManager { get; private set; }
        public IOutputManager OutputManager { get; private set; }
        public ISerializer Serializer { get; private set; }
        public ISettings Settings { get; set; }

        public ControlCore()
        {
            Serializer = new Serializer();
            FolderManager = new FolderManager();
            LoadSettings();
        }

        public void Dispose()
        {
            SaveSettings();
        }

        private void LoadSettings()
        {
            if (!File.Exists(FolderManager.SettingFile))
                Settings = new StartupSettings();
            else
            {
                try
                {
                    var data = File.ReadAllBytes(FolderManager.SettingFile);
                    Settings = Serializer.Deserialize&amp;amp;lt;StartupSettings&amp;amp;gt;(data) ?? new StartupSettings();
                }
                catch (Exception ex)
                {
                }
            }
        }

        private void SaveSettings()
        {
            try
            {
                var data = Serializer.Serialize(Settings);
                File.WriteAllBytes(FolderManager.SettingFile, data);
            }
            catch (Exception ex)
            {
            }
        }
    }
}

Here we host all folder paths loaded from a settings file – nothing more…

using System;
using System.IO;
using Client.Interfaces;

namespace Client.CoreSettings
{
    public class FolderManager : IFolderManager
    {
        public FolderManager()
        {
            MainDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Constants.PlatformName);
            CreateDirectoryIfNeeded(MainDirectory);

            WorkspaceDirectory = Path.Combine(MainDirectory, "Workspace");
            CreateDirectoryIfNeeded(WorkspaceDirectory);
        }

        public string MainDirectory { get; private set; }
        public string WorkspaceDirectory { get; private set; }

        public string SettingFile { get; private set; }

        public static void CreateDirectoryIfNeeded(string directory)
        {
            if (string.IsNullOrWhiteSpace(directory))
                throw new ArgumentNullException("directory");

            try
            {
                if (!Directory.Exists(directory))
                    Directory.CreateDirectory(directory);
            }
            catch (Exception ex)
            {
            }
        }
    }
}

To store and restore all the settings we need to serialize it. For this there is an class which becomes elevated by Protobuf-Net.

using System;
using System.IO;
using System.Windows.Media;
using Client.Interfaces;
using ProtoBuf.Meta;

namespace Client.CoreSettings
{
    public class Serializer : ISerializer
    {
        static Serializer()
        {
            RuntimeTypeModel.Default.Add(typeof(Color), false).Add("A", "R", "G", "B");
            RuntimeTypeModel.Default.CompileInPlace();
        }

        public byte[] Serialize(object object2Serialize)
        {
            if (object2Serialize == null)
                throw new ArgumentNullException("object2Serialize");

            try
            {
                using (var stream = new MemoryStream())
                {
                    ProtoBuf.Serializer.Serialize(stream, object2Serialize);
                    return stream.ToArray();
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public T Deserialize&amp;amp;lt;T&amp;amp;gt;(byte[] data)
        {
            if (data == null)
                throw new ArgumentNullException("data");

            try
            {
                using (var stream = new MemoryStream(data))
                    return ProtoBuf.Serializer.Deserialize&amp;amp;lt;T&amp;amp;gt;(stream);
            }
            catch (Exception ex)
            {
                return default(T);
            }
        }
    }
}

At least we need to handle all the stuff around sending the connection details to server app during startup or login. This is done by another class:

using Client.Interfaces;
using ProtoBuf;

namespace Client.CoreSettings
{
    [ProtoContract]
    public class StartupSettings : ISettings
    {
        public StartupSettings()
        {
            UserName = "";
            Host = "127.0.0.1";
            Port = 04504;
            CurrentCulture = "en-US";
        }

        [ProtoMember(1)]
        public string UserName { get; set; }

        [ProtoMember(2)]
        public byte[] Workspace { get; set; }

        [ProtoMember(4)]
        public string CurrentCulture { get; set; }

        [ProtoMember(5)]
        public string Host { get; set; }

        [ProtoMember(6)]
        public int Port { get; set; }
    }
}

bild1Now the project should look like in the picture here. Now lets move on with creating another project named Interfaces. This project will grow over time with every post until the client application is finished. So lets start with interfaces for the already covered classes.

Project “Interfaces”

I created an folder named Common to collect all the non specific interfaces. But this is not essential at least. So lets implement some interfaces:

namespace Client.Interfaces
{
    public interface ISerializer
    {
        byte[] Serialize(object obj);
        T Deserialize&amp;amp;lt;T&amp;amp;gt;(byte[] data);
    }
}
using System.Collections.Generic;
using ProtoBuf;

namespace Client.Interfaces
{
    [ProtoContract]
    public interface ISettings
    {
        string UserName { get; set; }
        byte[] Workspace { get; set; }
        string CurrentCulture { get; set; }
        string Host { get; set; }
        int Port { get; set; }
    }
}
using Client.Interfaces;

namespace Client.Interfaces
{
    public interface ISettingsManager
    {
        void SaveSettings(ISettings settings);
    }
}
using System;

namespace Client.Interfaces
{
    public class MessageEventArgs : EventArgs
    {
        public MessageEventArgs(string message)
        {
            Message = message;
        }

        public string Message { get; private set; }
    }
}
using System;

namespace Client.Interfaces
{
    public interface IOutputManager
    {
        ///
&amp;amp;lt;summary&amp;amp;gt;
        ///     Event raised when new message arrived
        /// &amp;amp;lt;/summary&amp;amp;gt;

        event EventHandler&amp;amp;lt;MessageEventArgs&amp;amp;gt; Message;

        ///
&amp;amp;lt;summary&amp;amp;gt;
        ///     Process message string, write message as Log Info and raise event Message
        /// &amp;amp;lt;/summary&amp;amp;gt;

        /// &amp;amp;lt;param name="message"&amp;amp;gt;&amp;amp;lt;/param&amp;amp;gt;
        void Print(string message);
    }
}
namespace Client.Interfaces
{
    public interface IFolderManager
    {
        string MainDirectory { get; }
        string WorkspaceDirectory { get; }

        string SettingFile { get; }
    }
}
using System;

namespace Client.Interfaces
{
    public interface ICore : IDisposable
    {
        IFolderManager FolderManager { get; }
        IOutputManager OutputManager { get; }
        IViewDispatcher ViewDispatcher { get; }
        ISettings Settings { get; set; }
        ISerializer Serializer { get; }
    }
}
namespace Client.Interfaces
{
    public static class Constants
    {
        public const string PlatformName = "ClientApp";
    }
}

bild1That’s it for now – about non View or ViewModel related interfaces. From now its three projects left from the working client application. The next posts are about these three projects in detail. Finally we need to add a project with our server service reference to handle all the client server data exchange stuff.

If you have suggestions or comments, feel free to let me know. To get a preview about upcoming topics or what was posted in past, please have a look here: Content++. If you like this Blog and don’t want to miss any update, just follow here at Twitter or Facebook.

programmingonacid_c7bda5_5340766

quantocracy-badge-130

One thought on “Client -III-

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s