Показать сообщение отдельно
Старый 10.06.2010, 03:07   #2
Dream
быдло
 
Регистрация: 05.08.2007
Сообщений: 1,435
Написано 614 полезных сообщений
(для 1,489 пользователей)
Радость Полу урок. Сериализация. Часть 2. Десериализация и параметры.

В предыдущей статье мы получили такой код :
public class XmlHelper
    
{
        
#region members
        
private static readonly Hashtable hash = new Hashtable(); 
        
#endregion

        #region Static
        
public static XmlSerializer GetSerializer(Type type)
        {
            
XmlSerializer res;
            
lock (hash)
            {

                
res hash[type.FullName] as XmlSerializer;
                if (
res == null)
                {
                    
res = new XmlSerializer(type);
                    
hash[type.FullName] = res;
                }
            }
            return 
res;
        }

        public static 
void WriteEntity(object objstring fileFullPath)
        {
            
XmlSerializer serializer GetSerializer(obj.GetType());
            
StringBuilder stringBuilder = new StringBuilder();
            
StringWriter w = new StringWriter(stringBuilderCultureInfo.InvariantCulture);
            
serializer.Serialize(wobj);
            
w.Close();
            
string xml stringBuilder.ToString();
            
StreamWriter sw = new StreamWriter(fileFullPath);
            
sw.Write(xml);
            
sw.Close();
        }
       
      
        
#endregion
    

Сегодня давайте приступим к десериализации, то есть в восстановлению класса из xml структуры, записанной ранее нами.
Это мы будем делать с помощью метода
T GetEntity<T>(string fileFullPath
, где Т - типа возвращаемого объекта, а string fileFullPath - путь к файлу из которого требуется извлечь структуру.
Выглядеть метод будет так
using (StreamReader reader = new StreamReader(fileFullPath))
            {
                
XmlSerializer dsr GetSerializer(typeof(T));
                return (
T)deSerializer.Deserialize(reader);
            } 
using (StreamReader reader = new StreamReader(fileFullPath))
            { 
мы создаём Потоковый ридер из файла, который мы получили в параметрах.
XmlSerializer deSerializerGetSerializer(typeof(T)); 
Так же как и в предыдущем методе, мы получаем сериализатор для даного типа.
в следующей строке, мы производим десериализацию из потока reader, с помощью полученного нами сериализатора deSerializer, и приводим его у требовавшемуся типу - Т который был указан при вызове метода:
return (T)deSerializer.Deserialize(reader); 
Вот собственно и всё! теперь можно записывать и получать экземпляры классов с помощью нашего помощника.

Вот пример кода:
Объявляем класс TempClass:
public class TempClass
    
{
        
#region _fields

        
private string _name;
        public 
int Id;
        
#endregion

        #region statics
        
public static int Count;
        public static 
int GetNextCount
        
{
            
get
            
{
                return ++
Count;
            }
        }
        
#endregion

        #region C'tos
        
public TempClass()
        {
            
Id GetNextCount;
        }
        
#endregion

        #region Propereties

        
public string Name
        
{
            
get
            
{
                return 
_name;
            }
            
set
            
{
                
_name value;
            }
        }

        
#endregion

    

Здесь я ввёл глобальные статические поля, что показать как работает сериализатор. при создании экземпляра класса TempClass, количество экземпляров увеличивается, что даёт нам возможность узнать какой по счёту этот экземпляр.
Далее:
class Program
    
{
       
        static 
void Main(string[] args)
        {
            
TempClass myClass=new TempClass();
            
myClass.Name "Xml test class";
            
XmlHelper.WriteEntity(myClass,@"C:\classes.xml");
            
myClass = new TempClass();
            
myClass.Name "Xml test class 2";
            
XmlHelper.WriteEntity(myClass, @"C:\classes1.xml");
         
TempClass deserializeClass XmlHelper.GetEntity<TempClass>(@"C:\classes.xml");
            
Console.Write(deserializeClass.Id+": name - "+deserializeClass.Name);
      }
    } 
Примечание: пример был создан на основе шаблона - Console application.

TempClass myClass=new TempClass();
            
myClass.Name "Xml test class"
Создаём экземпляр класса TempClass, и назначаем ему имя - "Xml test class"

Далее вызываем наш метотод для сериализации в файл @"C:\classes.xml":
XmlHelper.WriteEntity(myClass,@"C:\classes.xml"); 
Также повторяем для ещё одного экземпляра, для чистоты эксперимента:
myClass = new TempClass();
myClass.Name "Xml test class 2";
XmlHelper.WriteEntity(myClass, @"C:\classes1.xml"); 
Теперь, если посмотреть на диске C: вы увидите два Xml файла со структурой

<TempClass >
  <
Id>1</Id>
  <
Name>Xml test class</Name>
</
TempClass
Как в видите статические поля не сериализуюся.
Также поля, помеченные как приватные (а также как protected), тоже не сериализуются.

Остальные поля сериализовались с именем прописанном в коде.
В первом файле, поле Id будет равно 1, а во втором - 2, то есть можно быть уверенным что сериализовалось два разных экземпляра.

Идём дальше по коду.
TempClass deserializeClass XmlHelper.GetEntity<TempClass>(@"C:\classes.xml"); 
Здесь мы вызываем метод десериализации написанный нами в начале этой статьи. Пытаемся десериализировать файл "classes.xml".
Примечание: при десериализцаии вызывается конструктор по умолчанию (new()) который обязательно должен присутствовать в сериализуемом классе, также класс, который вы ходите сериализовать/десериализовать должен быть объявлен с модификатором видимости public.

и свойства полученного нами экземпляра в консоль, чтобы наглядно увидеть.
Console.Write(deserializeClass.Id+": name - "+deserializeClass.Name); 
в строке вы увидите что мы десериализовали из файла класс, который был объявлен и записан первым в файл classes.xml .

3.
А сейчас давайте поговорим о нюансах и некоторых возможностях серилизации/десериализации.

и так:
1)
Возможность исключения из сериализации/десериализации не нужных полей:
[XmlIgnore]
ставится перед полем/свойством, которое мы не хотим чтобы сериализировалось в файл.
Это может понадобится если ваш класс выполняет какие действия в свойствах, например, модифицируем на класс TempClass в класс MathClass и добавим ему несколько полей.
public class MathClass
    
{
        
#region _fields

        
private string _name;
        public 
int Id;
        private 
int _firstDigit;
        private 
int _secondDigit;

        
#endregion

        #region statics
        
public static int Count;
        
        public static 
int GetNextCount
        
{
            
get
            
{
                
Count++;
                return 
Count;
            }
        }
        
#endregion

        #region C'tos
        
public MathClass()
        {
            
Id GetNextCount;
        }
        
#endregion

        #region Propereties

        
public string Name
        
{
            
get
            
{
                return 
_name;
            }
            
set
            
{
                
_name value;
            }
        }

        public 
int SecondDigit
        
{
            
get { return _secondDigit; }
            
set _secondDigit value; }
        }

        public 
int FirstDigit
        
{
            
get { return _firstDigit; }
            
set _firstDigit value; }
        }
          [
XmlIgnore]

        public 
int Result
        
{
            
get
            
{
                return 
FirstDigit SecondDigit;
            }
            
        }
        
#endregion

    

Этот класс, при вызове получении свойства Result возвращает сумму двух полей - FirstDigit и
SecondDigit. но так как результат у нас обновляется автоматически нам нет надобности записывать его в файл, и мы ставим перед ним [XmlIgnore]. остальные же поля будут сериализованы в файл.
2)
В xml 3 типа структур:
- ROOT - коренная структура, в которую входят все под структуры. В этой роли выступает класс, который был передан на сериализацию. в нашем примере это класс MathClass. Посмотрите в xml, и вы увидите что основная структура тоже называется MathClass, это корень.
-Attribute - поля, которые будут записываться перед ">" начала текущей структуры.
- Element - под структуры в текущей структуре - по умолчанию, для всех свойств/полей класса при сериализации. В общем то, представляет собой сериализацию того класса, который содержится в этом самом поле/свойстве
Пример:
<MathClass Id="2" Name="Xml test class"> <!--Id и Name атрибуиты структуры-->
  <
SecondDigit>0</SecondDigit><!--Эллементы-->
  <
FirstDigit>0</FirstDigit><!--Эллементы-->
</
MathClass
Давайте попробуем изменить наш класс MathClass, чтобы получить такую структуру, как в примере.
Поставим перед полем Id модификатор
[XmlAttribute]
public 
int Id
, чтобы сделать его атрибутом класса. Также поступим и со свойством Name
[XmlAttribute]
        public 
string Name
        
{
            
get
            
{
                return 
_name;
            }
            
set
            
{
                
_name value;
            }
        } 
.
Теперь установим свойства SecondDigit и FirstDigit элементами нашего класса


[XmlElement]
        public 
int SecondDigit
        
{
            
get { return _secondDigit; }
            
set _secondDigit value; }
        }

        [
XmlElement]
        public 
int FirstDigit
        
{
            
get { return _firstDigit; }
            
set _firstDigit value; }
        } 
Вот и всё, теперь мы получим точна такую же структуру как в примере.
На сегодня всё, мы разобрались как считать структуру из файла, смогли установить какие поля нам не нужны при сохранении, а также, как делать нужные нам свойства полями.
В следующий раз я разберу как назначать мена сериализируемым объектам и ещё несколько нюансов, которые возникают при этом. До скорых!
(Offline)
 
Ответить с цитированием
Эти 10 пользователя(ей) сказали Спасибо Dream за это полезное сообщение:
ABTOMAT (10.06.2010), den (05.08.2010), h1dd3n (02.09.2010), Harter (12.06.2010), IGR (10.06.2010), Lestar (18.06.2011), Nex (10.06.2010), pax (10.06.2010), Radnk (25.08.2012), Randomize (10.06.2010)