SerializationBinder Class
Definition
Important
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
Allows users to control class loading and mandate what class to load.
public ref class SerializationBinder abstract
public abstract class SerializationBinder
[System.Serializable]
public abstract class SerializationBinder
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public abstract class SerializationBinder
type SerializationBinder = class
[<System.Serializable>]
type SerializationBinder = class
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type SerializationBinder = class
Public MustInherit Class SerializationBinder
- Inheritance
-
SerializationBinder
- Attributes
Examples
using namespace System;
using namespace System::IO;
using namespace System::Runtime::Serialization;
using namespace System::Runtime::Serialization::Formatters::Binary;
using namespace System::Reflection;
using namespace System::Security::Permissions;
ref class Version1ToVersion2DeserializationBinder;
[Serializable]
ref class Version1Type
{
public:
Int32 x;
};
[Serializable]
ref class Version2Type: public ISerializable
{
public:
Int32 x;
String^ name;
// The security attribute demands that code that calls
// this method have permission to perform serialization.
[SecurityPermissionAttribute(SecurityAction::Demand,SerializationFormatter=true)]
virtual void GetObjectData( SerializationInfo^ info, StreamingContext context )
{
info->AddValue( "x", x );
info->AddValue( "name", name );
}
private:
// The security attribute demands that code that calls
// this method have permission to perform serialization.
[SecurityPermissionAttribute(SecurityAction::Demand,SerializationFormatter=true)]
Version2Type( SerializationInfo^ info, StreamingContext context )
{
x = info->GetInt32( "x" );
try
{
name = info->GetString( "name" );
}
catch ( SerializationException^ )
{
// The 'name' field was not serialized because Version1Type
// did not contain this field.
// We will set this field to a reasonable default value.
name = "Reasonable default value";
}
}
};
ref class Version1ToVersion2DeserializationBinder sealed: public SerializationBinder
{
public:
virtual Type^ BindToType( String^ assemblyName, String^ typeName ) override
{
Type^ typeToDeserialize = nullptr;
// For each assemblyName/typeName that you want to deserialize to
// a different type, set typeToDeserialize to the desired type.
String^ assemVer1 = Assembly::GetExecutingAssembly()->FullName;
String^ typeVer1 = "Version1Type";
if ( assemblyName->Equals( assemVer1 ) && typeName->Equals( typeVer1 ) )
{
// To use a type from a different assembly version,
// change the version number using the following line of code.
// assemblyName = assemblyName.Replace("1.0.0.0", "2.0.0.0");
// To use a different type from the same assembly,
// change the type name.
typeName = "Version2Type";
}
// The following line of code returns the type.
typeToDeserialize = Type::GetType( String::Format( "{0}, {1}", typeName, assemblyName ) );
return typeToDeserialize;
}
};
ref class App
{
public:
static void Serialize()
{
// To serialize the objects, you must first open a stream for writing.
// We will use a file stream here.
FileStream^ fs = gcnew FileStream( "DataFile.dat",FileMode::Create );
try
{
// Construct a BinaryFormatter and use it
// to serialize the data to the stream.
BinaryFormatter^ formatter = gcnew BinaryFormatter;
// Construct a Version1Type Object and serialize it.
Version1Type^ obj = gcnew Version1Type;
obj->x = 123;
formatter->Serialize( fs, obj );
}
catch ( SerializationException^ e )
{
Console::WriteLine( "Failed to serialize. Reason: {0}", e->Message );
throw;
}
finally
{
fs->Close();
}
}
static void Deserialize()
{
// Declare the Version2Type reference.
Version2Type^ obj = nullptr;
// Open the file containing the data that we want to deserialize.
FileStream^ fs = gcnew FileStream( "DataFile.dat",FileMode::Open );
try
{
// Construct a BinaryFormatter and use it
// to deserialize the data from the stream.
BinaryFormatter^ formatter = gcnew BinaryFormatter;
// Construct an instance of our
// Version1ToVersion2TypeSerialiationBinder type.
// This Binder type knows how to deserialize a Version1Type
// Object* to a Version2Type Object.
formatter->Binder = gcnew Version1ToVersion2DeserializationBinder;
obj = dynamic_cast<Version2Type^>(formatter->Deserialize( fs ));
}
catch ( SerializationException^ e )
{
Console::WriteLine( "Failed to deserialize. Reason: {0}", e->Message );
throw;
}
finally
{
fs->Close();
}
// To prove that a Version2Type Object* was deserialized,
// display the Object's type and fields to the console.
Console::WriteLine( "Type of Object deserialized: {0}", obj->GetType() );
Console::WriteLine( "x = {0}, name = {1}", obj->x, obj->name );
}
};
[STAThread]
int main()
{
App::Serialize();
App::Deserialize();
return 0;
}
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;
class App
{
[STAThread]
static void Main()
{
Serialize();
Deserialize();
}
static void Serialize()
{
// To serialize the objects, you must first open a stream for writing.
// Use a file stream here.
FileStream fs = new FileStream("DataFile.dat", FileMode.Create);
try
{
// Construct a BinaryFormatter and use it
// to serialize the data to the stream.
BinaryFormatter formatter = new BinaryFormatter();
// Construct a Version1Type object and serialize it.
Version1Type obj = new Version1Type();
obj.x = 123;
formatter.Serialize(fs, obj);
}
catch (SerializationException e)
{
Console.WriteLine("Failed to serialize. Reason: " + e.Message);
throw;
}
finally
{
fs.Close();
}
}
static void Deserialize()
{
// Declare the Version2Type reference.
Version2Type obj = null;
// Open the file containing the data that you want to deserialize.
FileStream fs = new FileStream("DataFile.dat", FileMode.Open);
try
{
// Construct a BinaryFormatter and use it
// to deserialize the data from the stream.
BinaryFormatter formatter = new BinaryFormatter();
// Construct an instance of our the
// Version1ToVersion2TypeSerialiationBinder type.
// This Binder type can deserialize a Version1Type
// object to a Version2Type object.
formatter.Binder = new Version1ToVersion2DeserializationBinder();
obj = (Version2Type) formatter.Deserialize(fs);
}
catch (SerializationException e)
{
Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
throw;
}
finally
{
fs.Close();
}
// To prove that a Version2Type object was deserialized,
// display the object's type and fields to the console.
Console.WriteLine("Type of object deserialized: " + obj.GetType());
Console.WriteLine("x = {0}, name = {1}", obj.x, obj.name);
}
}
[Serializable]
class Version1Type
{
public Int32 x;
}
[Serializable]
class Version2Type : ISerializable
{
public Int32 x;
public String name;
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("x", x);
info.AddValue("name", name);
}
private Version2Type(SerializationInfo info, StreamingContext context)
{
x = info.GetInt32("x");
try
{
name = info.GetString("name");
}
catch (SerializationException)
{
// The "name" field was not serialized because Version1Type
// did not contain this field.
// Set this field to a reasonable default value.
name = "Reasonable default value";
}
}
}
sealed class Version1ToVersion2DeserializationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
Type typeToDeserialize = null;
// For each assemblyName/typeName that you want to deserialize to
// a different type, set typeToDeserialize to the desired type.
String assemVer1 = Assembly.GetExecutingAssembly().FullName;
String typeVer1 = "Version1Type";
if (assemblyName == assemVer1 && typeName == typeVer1)
{
// To use a type from a different assembly version,
// change the version number.
// To do this, uncomment the following line of code.
// assemblyName = assemblyName.Replace("1.0.0.0", "2.0.0.0");
// To use a different type from the same assembly,
// change the type name.
typeName = "Version2Type";
}
// The following line of code returns the type.
typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
typeName, assemblyName));
return typeToDeserialize;
}
}
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Reflection
Imports System.Security.Permissions
Class App
<STAThread()> Shared Sub Main()
Serialize()
Deserialize()
End Sub
Shared Sub Serialize()
' To serialize the objects, you must first open a stream for writing.
' Use a file stream here.
Dim fs As New FileStream("DataFile.dat", FileMode.Create)
Try
' Construct a BinaryFormatter and use it
' to serialize the data to the stream.
Dim formatter As New BinaryFormatter
' Construct a Version1Type object and serialize it.
Dim obj As New Version1Type
obj.x = 123
formatter.Serialize(fs, obj)
Catch e As SerializationException
Console.WriteLine("Failed to serialize. Reason: " & e.Message)
Throw
Finally
fs.Close()
End Try
End Sub
Shared Sub Deserialize()
' Declare the Version2Type reference.
Dim obj As Version2Type = Nothing
' Open the file containing the data that you want to deserialize.
Dim fs As New FileStream("DataFile.dat", FileMode.Open)
Try
' Construct a BinaryFormatter and use it
' to deserialize the data from the stream.
Dim formatter As New BinaryFormatter
' Construct an instance of the
' Version1ToVersion2TypeSerialiationBinder type.
' This Binder type can deserialize a Version1Type
' object to a Version2Type object.
formatter.Binder = New Version1ToVersion2DeserializationBinder
obj = DirectCast(formatter.Deserialize(fs), Version2Type)
Catch e As SerializationException
Console.WriteLine("Failed to deserialize. Reason: " & e.Message)
Throw
Finally
fs.Close()
End Try
' To prove that a Version2Type object was deserialized,
' display the object's type and fields to the console.
Console.WriteLine("Type of object deserialized: {0}", obj.GetType())
Console.WriteLine("x = {0}, name = {1}", obj.x, obj.name)
End Sub
End Class
<Serializable()> Class Version1Type
Public x As Int32
End Class
<Serializable()> Class Version2Type
Implements ISerializable
Public x As Int32
Public name As String
' The security attribute demands that code that calls
' this method have permission to perform serialization.
<SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter:=True)> _
Private Sub GetObjectData(ByVal info As SerializationInfo, _
ByVal context As StreamingContext) Implements ISerializable.GetObjectData
info.AddValue("x", x)
info.AddValue("name", name)
End Sub
' The security attribute demands that code that calls
' this method have permission to perform serialization.
<SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter:=True)> _
Private Sub New(ByVal info As SerializationInfo, _
ByVal context As StreamingContext)
x = info.GetInt32("x")
Try
name = info.GetString("name")
Catch e As SerializationException
' The "name" field was not serialized because
' Version1Type did not contain this field.
' Set this field to a reasonable default value.
name = "Reasonable default value"
End Try
End Sub
End Class
NotInheritable Class Version1ToVersion2DeserializationBinder
Inherits SerializationBinder
Public Overrides Function BindToType(ByVal assemblyName As String, _
ByVal typeName As String) As Type
Dim typeToDeserialize As Type = Nothing
' For each assemblyName/typeName that you want to deserialize
' to a different type, set typeToDeserialize to the desired type.
Dim assemVer1 As String = [Assembly].GetExecutingAssembly().FullName
Dim typeVer1 As String = GetType(Version1Type).FullName
If assemblyName = assemVer1 And typeName = typeVer1 Then
' To use a type from a different assembly version,
' change the version number.
' To do this, uncomment the following code.
' assemblyName = assemblyName.Replace("1.0.0.0", "2.0.0.0")
' To use a different type from the same assembly,
' change the type name.
typeName = typeName.Replace("Version1Type", "Version2Type")
End If
' The following code returns the type.
typeToDeserialize = Type.GetType(String.Format("{0}, {1}", typeName, _
assemblyName))
Return typeToDeserialize
End Function
End Class
Remarks
Insecure serializers
Warning
BinaryFormatter
is insecure and can't be made secure. For more information, see the BinaryFormatter security guide.
During serialization, a formatter transmits the information required to create an instance of an object of the correct type and version. This information generally includes the full type name and assembly name of the object. The assembly name includes the name, version, and strong name (see Strong-Named Assemblies) hash of the assembly. By default, deserialization uses this information to create an instance of an identical object (with the exception of any assembly loading restricted by the security policy). Some users need to control which class to load, either because the class has moved between assemblies or a different version of the class is required on the server and client.
SerializationBinder can not be used for security. There might be some security exploits when you are trying to deserialize some data from an untrusted source. The binder gives you an opportunity to inspect what types are being loaded in your application domain, but this doesn't guarantee an exploit is not possible. For more information see the BinaryFormatter security guide. You can then either maintain list of denied types or a list of allowed types and restrict which types are being loaded and instantiated. In addition, be mindful of what information is being put out on the wire. You may want to use transport or message security when sending type names or other data on the network.
Warning
Only use SerializationBinder if you are completely sure of what information is being serialized. Malicious types can cause unexpected behavior.
This is an abstract base class. All binders extend this class.
Notes to Implementers
When you inherit from SerializationBinder, you must override the following member: BindToType(String, String).
Constructors
SerializationBinder() |
Initializes a new instance of the SerializationBinder class. |
Methods
BindToName(Type, String, String) |
When overridden in a derived class, controls the binding of a serialized object to a type. |
BindToType(String, String) |
When overridden in a derived class, controls the binding of a serialized object to a type. |
Equals(Object) |
Determines whether the specified object is equal to the current object. (Inherited from Object) |
GetHashCode() |
Serves as the default hash function. (Inherited from Object) |
GetType() |
Gets the Type of the current instance. (Inherited from Object) |
MemberwiseClone() |
Creates a shallow copy of the current Object. (Inherited from Object) |
ToString() |
Returns a string that represents the current object. (Inherited from Object) |