Средства сериализации-десериализации в ICSSoft.STORMNET.Windows.Forms.Utils
В сборке ICSSoft.STORMNET.Windows.Forms
реализован класс ICSSoft.STORMNET.Windows.Forms.Utils
, предоставляющий, в частности, методы для сериализации-десериализации, которые применимы в т.ч. для функции ограничения. Данные методы представляют собой обертку над соответствующими методами сборки ICSSoft.STORMNET.Tools
, и выполняют обращение к ней.
Методы сериализации класса ICSSoft.STORMNET.Windows.Forms.Utils
:
ObjectToString
Назначение: Сериализация в строку при помощи SoapFormatter
.
Параметры:
o
- Объект
Возвращаемый результат: Строка.
Сигнатура:
public static string ObjectToString(object o)
{
return ICSSoft.STORMNET.Tools.ToolXML.ObjectToString(o);
}
ObjectFromString
Назначение: Десериализация из строки при помощи SoapFormatter
.
Параметры:
s
- Сериализованный объект
Возвращаемый результат: Востановленный объект.
Сигнатура:
public static object ObjectFromString(string s)
{
return ICSSoft.STORMNET.Tools.ToolXML.ObjectFromString(s);
}
ObjectToBinaryString
Назначение: Сериализация в строку при помощи BinaryFormatter
.
Параметры:
o
- Объект
Возвращаемый результат: Строка.
Сигнатура:
public static string ObjectToBinaryString(object o)
{
return ICSSoft.STORMNET.Tools.ToolBinarySerializer.ObjectToString(o);
}
ObjectFromBinaryString
Назначение: Десериализация из строки при помощи BinaryFormatter
(если не получится, то попробуем SoapFormatter
- для совместимости с унаследованными данными).
Параметры:
s
- Сериализованный объект
Возвращаемый результат: Востановленный объект.
Сигнатура:
public static object ObjectFromBinaryString(string s)
{
object retObj;
try
{
retObj = ICSSoft.STORMNET.Tools.ToolBinarySerializer.ObjectFromString(s);
}
catch
{
retObj = ICSSoft.STORMNET.Tools.ToolXML.ObjectFromString(s);
}
return retObj;
}
На [форме задания ограничений] при сохранении (восстановлении) LimitFunction используются методы Utils.ObjectToBinaryString
(Utils.ObjectFromBinaryString
), т.е. сериализуются ограничения с помощью бинарной сериализации, а восстанавливаются как бинарные строки, так и SOAP, т.к. в ранних версиях технологии использовалась SOAP-сериализация.
Пример SOAP-сериализации LimitFunction
Function fn = FunctionBuilder.BuildAnd(
FunctionBuilder.BuildEquals("ПарамПамПам", "кто ходит в гости по утрам"),
FunctionBuilder.BuildOr(
FunctionBuilder.BuildEquals("ТотПоступаетМудро", Environment.UserName),
FunctionBuilder.BuildIsNull("НаТоОноИУтро")
)
);
string serializedFn = Utils.ObjectToString((new ExternalLangDef()).FunctionToSimpleStruct(fn));
Assert.IsNotNull(serializedFn);
Console.WriteLine(serializedFn);
Function восставшийИзНебытия = (
new ExternalLangDef()).FunctionFromSimpleStruct(Utils.ObjectFromString(serializedFn));
Assert.IsNotNull(восставшийИзНебытия);
Пример бинарной сериализации LimitFunction
Этот вид сериализации более производительный и строки получаются короче.
string fnStr = "";
string serializedFn;
AdvansedLimit advlimit = new AdvansedLimit();
ExternalLangDef externalLangDef = ExternalLangDef.LanguageDef;
advlimit.FromSimpleValue(Utils.ObjectFromString(_serializedFunc), externalLangDef);
Function fn = advlimit.Function;
serializedFn = Utils.ObjectToBinaryString(externalLangDef.FunctionToSimpleStruct(fn));
Assert.IsNotNull(serializedFn);
восставшийИзНебытия =
externalLangDef.FunctionFromSimpleStruct(Utils.ObjectFromBinaryString(serializedFn));
Assert.IsNotNull(восставшийИзНебытия);
Возможная проблема десериализации
В коде выше используется конструкция advlimit.FromSimpleValue
, которая на основании объекта особого вида строит непосредственно ограничение. В структуре передаваемого объекта особого вида, среди прочих, есть AssemblyQualifiedName
типа, из-за чего могут возникнуть проблемы при десериализации: например, если ограничение было создано с неподписанной сборкой, а требуется открыть уже с версией, что была подписана (соответственно, AssemblyQualifiedName
типа изменилось и его нельзя получить через Type.GetType(...)
), и др. Для этого случая добавлен делегат, который позволяет определить собственный дополнительный метод для получения типа по его имени.
namespace ICSSoft.STORMNET.Windows.Forms
{
public class ExternalLangDef
{
/// <summary> Делегат для получения типа по его имени в методе SimpleValueToDataObject </summary>
public static TypeResolveDelegate ExtraTypeResolver = null;
//...
}
/// <summary>
/// Делегат для получения типа по его имени (используется в особых случаях, когда стандартные методы почему-то не помогают)
/// </summary>
/// <param name="typeName">Имя типа.</param>
/// <returns> Сформированный по имени тип </returns>
public delegate Type TypeResolveDelegate(string typeName);
}
Ниже представлен пример использования данного делегата:
// ...
var obj = ICSSoft.STORMNET.Windows.Forms.Utils.ObjectFromBinaryString(data);
var advansedLimit = new AdvansedLimit();
var externalLangDef = new ExternalLangDef();
ExternalLangDef.ExtraTypeResolver = ExtraTypeResolver;
advansedLimit.FromSimpleValue(obj, externalLangDef);
ExternalLangDef.ExtraTypeResolver = null;
var result = advansedLimit;
//...
}
private Type ExtraTypeResolver(string typeName)
{
if (typeName == "IIS.University.ВидПодразделения, University(Objects), Version=1.0.0.1, Culture=neutral, PublicKeyToken=null")
{
return typeof(IIS.University.ВидПодразделения);
}
return null;
}