[SIZE=2][[/SIZE][SIZE=2][COLOR=#008080]Serializable[/COLOR][/SIZE][SIZE=2]]
[/SIZE][SIZE=2][COLOR=#0000ff]struct [/COLOR][/SIZE][SIZE=2][COLOR=#008080]ServerClass[/COLOR][/SIZE][SIZE=2][COLOR=#008000]//серверный тип
[/COLOR][/SIZE][SIZE=2]{
[/SIZE][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]string[/COLOR][/SIZE][SIZE=2] Value1;
[/SIZE][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][SIZE=2][COLOR=#008080]DateTime[/COLOR][/SIZE][SIZE=2] Value2;
}
[/SIZE][SIZE=2][COLOR=#0000ff]class [/COLOR][/SIZE][SIZE=2][COLOR=#008080]MainClass
[/COLOR][/SIZE][SIZE=2]{
[/SIZE][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]static [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]void[/COLOR][/SIZE][SIZE=2] Main([/SIZE][SIZE=2][COLOR=#0000ff]string[/COLOR][/SIZE][SIZE=2][] args)
{
[/SIZE][SIZE=2][COLOR=#008080]ServerClass[/COLOR][/SIZE][SIZE=2] value; [/SIZE][SIZE=2][COLOR=#008000]//создаём экземпляр
[/COLOR][/SIZE][SIZE=2]value.Value1 = [/SIZE][SIZE=2][COLOR=#800000]"Hello, world"[/COLOR][/SIZE][SIZE=2];
value.Value2 = [/SIZE][SIZE=2][COLOR=#008080]DateTime[/COLOR][/SIZE][SIZE=2].Now;
System.Runtime.Serialization.Formatters.Binary.[/SIZE][SIZE=2][COLOR=#008080]BinaryFormatter[/COLOR][/SIZE][SIZE=2] formatter = [/SIZE][SIZE=2][COLOR=#0000ff]new[/COLOR][/SIZE][SIZE=2] System.Runtime.Serialization.Formatters.Binary.[/SIZE][SIZE=2][COLOR=#008080]BinaryFormatter[/COLOR][/SIZE][SIZE=2](); [/SIZE][SIZE=2][COLOR=#008000]//создаём простой двоичный форматтер
[/COLOR][/SIZE][SIZE=2][COLOR=#008080]Stream[/COLOR][/SIZE][SIZE=2] serialStream = [/SIZE][SIZE=2][COLOR=#0000ff]new [/COLOR][/SIZE][SIZE=2][COLOR=#008080]FileStream[/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#800000]"serverValueInfo"[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#008080]FileMode[/COLOR][/SIZE][SIZE=2].Create); [/SIZE][SIZE=2][COLOR=#008000]//создаём файл-обменник
[/COLOR][/SIZE][SIZE=2]formatter.Serialize(serialStream, value); [/SIZE][SIZE=2][COLOR=#008000]//сериализуем объект
[/COLOR][/SIZE][SIZE=2]serialStream.Close(); [/SIZE][SIZE=2][COLOR=#008000]//закрываем файл
[/COLOR][/SIZE][SIZE=2]}
}
[/SIZE]
Сериализация
Сериализация - это преобразование объекта из параллельной формы в последовательную.
Сериализация лежит в основе механизма .NET Remoting, да и вообще это полезная штука когда нужно сохранить состояние объекта. Данный пример демонстрирует, как могут работать два приложения архитектуры клиент-сервер, через сериализацию. В качестве среды хранения состояний используется файл. Вот через него и сообщаются клиентское и серверное сообщение. Серверное приложение помимо значения хранит ещё и информацию о классе. Клиентское приложение не имеет прямого доступа к серверному классу а работает с нимм жерез Reflection.
Серверное приложение
Код:
Теперь клиентское приложение десериализует объект выводит и его значение. На клиентской стороне класс ServerClass не объявлен, известно, что у экземпляра серверного класса есть два поля Value1 и Value2 и известны типы этих полей.
Код:
[SIZE=2]System.Runtime.Serialization.Formatters.Binary.[/SIZE][SIZE=2][COLOR=#008080]BinaryFormatter[/COLOR][/SIZE][SIZE=2] formatter = [/SIZE][SIZE=2][COLOR=#0000ff]new[/COLOR][/SIZE][SIZE=2] System.Runtime.Serialization.Formatters.Binary.[/SIZE][SIZE=2][COLOR=#008080]BinaryFormatter[/COLOR][/SIZE][SIZE=2]();[/SIZE][SIZE=2][COLOR=#008000]//создаём простой двоичный форматтер
[/COLOR][/SIZE][SIZE=2][COLOR=#008080]Stream[/COLOR][/SIZE][SIZE=2] serialStream = [/SIZE][SIZE=2][COLOR=#0000ff]new [/COLOR][/SIZE][SIZE=2][COLOR=#008080]FileStream[/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#800000]"serverValueInfo"[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#008080]FileMode[/COLOR][/SIZE][SIZE=2].Open);[/SIZE][SIZE=2][COLOR=#008000]//открываем файл обменник
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]object[/COLOR][/SIZE][SIZE=2] serverInstance = formatter.Deserialize(serialStream); [/SIZE][SIZE=2][COLOR=#008000]//десериализуем
[/COLOR][/SIZE][SIZE=2][COLOR=#008080]Type[/COLOR][/SIZE][SIZE=2] serverClass = serverInstance.GetType(); [/SIZE][SIZE=2][COLOR=#008000]//получаем метаданные о серверном типе
[/COLOR][/SIZE][SIZE=2][COLOR=#008080]Console[/COLOR][/SIZE][SIZE=2].WriteLine(serverClass.GetField([/SIZE][SIZE=2][COLOR=#800000]"Value1"[/COLOR][/SIZE][SIZE=2]).GetValue(serverInstance)); [/SIZE][SIZE=2][COLOR=#008000]//получаем значение поля Value1
[/COLOR][/SIZE][SIZE=2][COLOR=#008080]Console[/COLOR][/SIZE][SIZE=2].WriteLine(serverClass.GetField([/SIZE][SIZE=2][COLOR=#800000]"Value2"[/COLOR][/SIZE][SIZE=2]).GetValue(serverInstance)); [/SIZE][SIZE=2][COLOR=#008000]//получаем значение поля Value2
[/COLOR][/SIZE][SIZE=2]serverInstance = serverClass.InvokeMember([/SIZE][SIZE=2][COLOR=#800000]"this"[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#008080]BindingFlags[/COLOR][/SIZE][SIZE=2].CreateInstance, [/SIZE][SIZE=2][COLOR=#0000ff]null[/COLOR][/SIZE][SIZE=2], serverClass, [/SIZE][SIZE=2][COLOR=#0000ff]null[/COLOR][/SIZE][SIZE=2]); [/SIZE][SIZE=2][COLOR=#008000]//создаём новый экземпляр класса ServerClass и теперь можно менять его поля
[/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2][COLOR=#008080]Stream[/COLOR][/SIZE][SIZE=2] serialStream = [/SIZE][SIZE=2][COLOR=#0000ff]new [/COLOR][/SIZE][SIZE=2][COLOR=#008080]FileStream[/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#800000]"serverValueInfo"[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#008080]FileMode[/COLOR][/SIZE][SIZE=2].Open);[/SIZE][SIZE=2][COLOR=#008000]//открываем файл обменник
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]object[/COLOR][/SIZE][SIZE=2] serverInstance = formatter.Deserialize(serialStream); [/SIZE][SIZE=2][COLOR=#008000]//десериализуем
[/COLOR][/SIZE][SIZE=2][COLOR=#008080]Type[/COLOR][/SIZE][SIZE=2] serverClass = serverInstance.GetType(); [/SIZE][SIZE=2][COLOR=#008000]//получаем метаданные о серверном типе
[/COLOR][/SIZE][SIZE=2][COLOR=#008080]Console[/COLOR][/SIZE][SIZE=2].WriteLine(serverClass.GetField([/SIZE][SIZE=2][COLOR=#800000]"Value1"[/COLOR][/SIZE][SIZE=2]).GetValue(serverInstance)); [/SIZE][SIZE=2][COLOR=#008000]//получаем значение поля Value1
[/COLOR][/SIZE][SIZE=2][COLOR=#008080]Console[/COLOR][/SIZE][SIZE=2].WriteLine(serverClass.GetField([/SIZE][SIZE=2][COLOR=#800000]"Value2"[/COLOR][/SIZE][SIZE=2]).GetValue(serverInstance)); [/SIZE][SIZE=2][COLOR=#008000]//получаем значение поля Value2
[/COLOR][/SIZE][SIZE=2]serverInstance = serverClass.InvokeMember([/SIZE][SIZE=2][COLOR=#800000]"this"[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#008080]BindingFlags[/COLOR][/SIZE][SIZE=2].CreateInstance, [/SIZE][SIZE=2][COLOR=#0000ff]null[/COLOR][/SIZE][SIZE=2], serverClass, [/SIZE][SIZE=2][COLOR=#0000ff]null[/COLOR][/SIZE][SIZE=2]); [/SIZE][SIZE=2][COLOR=#008000]//создаём новый экземпляр класса ServerClass и теперь можно менять его поля
[/COLOR][/SIZE]
Следует отметить несколько плюсов такой реализации клиент-серверного приложения:
1) Отсутствует типовая зависимость кода клиента от кода сервера. Таким образом, с выходом новых версий серверной части клиент менять не придётся, даже если имя серверного класса ServerClass было изменено на другое.
2) Более простая модель по сравнению с .NET Remoting. Естественно, в такой реализации нет Singleton и Singlecall объектов, авторизации и всё такое.
Если вместо обмена использовать не файл а протоклы, то это уже будет полноценное сетевое приложения. Двоичный форматтер следует изменить на SOAP-форматтер.
Интересная статейка про сериализацию