Martin's Tex-Blog

Posts on programming and generally technical topics

Archive for the ‘MCTS 70-536’ Category

Advanced serialization tips

leave a comment »


Seralization knowledge not fully covered by official training kit.  These are actually notes from CLR via C# chapter 24.

1. SoapFormatter as of .NET 3.5 is obsolete, for production code use XmlSerializer or DataContractSerializer.
2. Instances can be deep cloned using binary serialization, remember to set:
bin_formatter.Context = new StreamingContext(StreamingContextStates.Clone);
3. You can serialize multiple objects to single stream
4. If You serialize instances of objects which are located in custom loaded assemblies (using LoadFrom), then SerializationExceptin might be thrown. To load assembly when requested, implement delegate that matches System.ResolveEventHandler and register this method with System.AppDomain’s AssemblyResolve event just before deserialization and remove it after it.
5. If some of the objects in the graph are not serializable, then exception will be thrown. It is thrown not before serialization, it can happen any time during it. This can cause resulting stream to contain corrupt data. In order to fail gracefully, serialize to memory stream, and if all is ok, send it to network stream etc.
6. The SerializableAttribute custom attribute may be applied to reference types (class), value types (struct), enumerated types (enum), and delegate types (delegate) only. But since enumerated types and delegates are serializable by default, it makes no sense to add this attribute to them.
7. Serializable attribute is not being inherited, if super class is non serializable then subclasses are not either.
8. Do not set Serializable to automatically generated properties, their names can change during compilation, making it not possible to deserialize.
9. Formatters makes use of FormatterServices class for serialization and deserialization, steps are as follows:

Serialization:
– Call FormatterServices.GetSerializableMembers to get MemberInfo[].
– Then call FormatterServices.GetObjectData to get array of values for each MemberInfo instance in the above array.
– Store assembly identity and type’s full name.
– Store each member, their type, name and value.

Deserialization:
– Load assembly identity information and if required load it. Call FormatterServices.GetTypeFromAssembly. This call returns System.Type that represents object to be deserialized.
– Call FormatterServices.GetUninitializedObject with previously returned System.Type, this returns an non-constructed object, with fields set to zero values.
– Now call FormatterServices.GetSerializableMembers to get MemberInfo[]. Those members will need to be deserialized.
– Formatter creates object data from the stream, those will be values of our members.
– With all prepared data call FormatterServices.PopulateObjectMembers, it requires reference to object, MemberInfo[] and Object[] – with values (deserialized in step above).

10. Implementation of ISerializable interface (to get freedom of how serialization happens and get rid of slow reflection), requires implementing its methods in each subclass, and also calling in them, super class versions.
11. Always add followng attribute to your ISerializable.GetObjectdata: [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]. This will prevent outside code from using this method in some malicious ways.
12. When using SerializationInfo class in c-tor, you should call the same Get* methods types as in ISerializable.GetObjectData. If there is a mismatch when deserializing given data, framework will try to convert it with IFormatterConverter, which internally calls System.Convert for core types. For other types it uses type’s IConvertible implementation.
13. SerializationInfo also provides enumerator, which returns SerializationEntry instances.
14. To custom serialize class which base type does not implement ISerializable, use this.GetType().BaseType, and serialize/deserialize it manually. This might be not possible with private fields.
15. Serializing a Type as a different Type, and Deserializing as a different object. This is of use when using singletons, DBNull object. For serialization:
– Add to ISerialization.GetObjectData, SerializationInfo.SetType() method call. As a parameter specify type of custom class that derives from IObjectReference.
16. Serialization surrogates: this is a technique that allows to serialize types not designed for serialization, to deserialize type to a new version, etc.. It is realized by createing class that implements ISerializationSurrogate interface. Its methods GetObjectData and SetObjectData are used for serialization and deserialization. In orderd to let Formatter know about our serializing surrogate implementation, create and initilize SurrogateSelector class and set it to Formatters SurrogateSelector property.
17. The BinaryFormatter class has a bug that prevents a surrogate from serializing objects with references to each other. For fix look into CLR Via C#.
18. Finally there is a technique to deserialize data to a different object than the one used during serialization. This is of use when new version of type is created, or type is moved to other assembly, client want to deserialize data from server to different local type. To use it implement SerializationBinder abstract class, and set it to Formatter’s Binder property.

Below are notes from other sources:

19. ObjectManager tracks deserialized objects. Formatter uses it to check if given reference is backward reference – its object was already deserialized, or it is forward reference – instance was not yet deserialized – this requires recording fixup with ObjectManager. Fixup means that reference will be assigned correct object in the future when actual object will get deserialized.
20. Marshaling is the process of packaging and sending remote procedure calls across process and application boundaries using serialization and deserialization.

Advertisements

Written by Marcin

March 27, 2011 at 4:50 pm

Posted in Linux, MCTS 70-536

Tagged with

Chapter 3 – Practice 2 solution code

leave a comment »


Practice 2 Write a Console application that processes your %Windir%\WindowsUpdate.log file and displays the time, date, and exit code for any rows that list an exit code.

    1 /// Make copy since it is open and used by system
    2 File.Copy(
    3   @"c:\windows\WindowsUpdate.log", 
    4   @"c:\windows\WindowsUpdate.log_",true );
    5 string sf = "";
    6 using (
    7   FileStream fs = new FileStream(
    8     @"c:\windows\WindowsUpdate.log_", 
    9     FileMode.Open, FileAccess.Read)
   10 )
   11 {
   12   StreamReader sr = new StreamReader(fs);
   13   sf = sr.ReadToEnd();
   14 }
   15 Match m = Regex.Match(sf,
   16   @"^(?<date>\d{4}-\d{2}-\d{2})" +
   17   @"\s+" +
   18   @"(?<time>\d{2}:\d{2}:\d{2}:\d+)" +
   19   @".*?exit code\s=\s(?<code>[a-f0-9x]+).*$"
   20   , RegexOptions.Multiline | RegexOptions.IgnoreCase);
   21 while (m.Success)
   22 {
   23   Console.WriteLine(
   24     "date: " + m.Groups["date"] + 
   25     "\ttime: " + m.Groups["time"] + 
   26     "\tcode: " + m.Groups["code"]);
   27   m = m.NextMatch();
   28 }

Written by Marcin

March 8, 2011 at 11:40 pm

Posted in MCTS 70-536

TypeForwardedTo attribute in action

leave a comment »


If you will try to test this attribute as it is described in MCTS Self-Paced Training Kit (70-536) in chapter 1 on pg. 48 then you might get into trouble. I don’t mean it is wrong,¬† but it is missing some intricacies. One is that type being moved must be in the same namespace as the original one. Suppose you have initially:

1.

Application.cs

ClassLibrary1.cs

using System;
namespace ClassLibrary1
{
public class Class1
{
}
}

ClassLibrary1.cs makes into ClassLibrary1.dll and Application.cs into Application.exe. Application.exe references ClassLibrary1.dll and all is working well, until someone decides to clean up code and move ClassLibrary1.Class1 into ClassLibrary2.dll. With the help of TypeForwardedTo you dont have to recompile application.exe, but only ClassLibrary1.dll and ClassLibrary2.dll. Now we have to do below changes:

2.

Application.cs – No! changes here

ClassLibrary1.cs – remember to reference in ClassLibrary1.dll a new library : ClassLibrary2.dll

using System;
using System.Runtime.CompilerServices;
using ClassLibrary2;

[assembly: TypeForwardedTo(typeof(ClassLibrary1.Class1))]

namespace ClassLibrary1
{
public class Class1Ex /// there is no more Class1 type here
{
}
}

ClassLibrary2.cs – New class, this is where Class1 type is being forwarded

using System;

namespace ClassLibrary1 // forwarded type, same as in ClassLibrary1.dll
{
public class Class1
{
}
}

namespace ClassLibrary2
{
public class SomeClass // some dummy class
{
}
}

If you are seeing exceptions running Application.exe then this might mean that you have not defined correctly in ClassLibrary2 a ClassLibrary1.Class1 type.

Written by Marcin

January 3, 2011 at 10:54 pm

Posted in MCTS 70-536