@@ -98,14 +98,41 @@ enum StreamReaderAlignment : int
9898 } ;
9999
100100 /// <summary>
101- /// These settings apply to use of Serializer and Deserializer specifically .
101+ /// Settings used by <code> Serializer</code> and <code> Deserializer</code> .
102102 /// </summary>
103103#if FASTSERIALIZATION_PUBLIC
104104 public
105105#endif
106- sealed class SerializationConfiguration
106+ sealed class SerializationSettings
107107 {
108- public StreamLabelWidth StreamLabelWidth { get ; set ; } = StreamLabelWidth . EightBytes ;
108+ internal StreamLabelWidth StreamLabelWidth { get ; }
109+
110+ internal StreamReaderAlignment StreamReaderAlignment { get ; }
111+
112+ public static SerializationSettings Default { get ; } = new SerializationSettings (
113+ StreamLabelWidth . EightBytes ,
114+ StreamReaderAlignment . EightBytes ) ;
115+
116+ public SerializationSettings WithStreamLabelWidth ( StreamLabelWidth width )
117+ {
118+ return new SerializationSettings (
119+ width ,
120+ StreamReaderAlignment ) ;
121+ }
122+
123+ public SerializationSettings WithStreamReaderAlignment ( StreamReaderAlignment alignment )
124+ {
125+ return new SerializationSettings (
126+ StreamLabelWidth ,
127+ alignment ) ;
128+ }
129+
130+ private SerializationSettings (
131+ StreamLabelWidth streamLabelWidth , StreamReaderAlignment streamReaderAlignment )
132+ {
133+ StreamLabelWidth = streamLabelWidth ;
134+ StreamReaderAlignment = streamReaderAlignment ;
135+ }
109136 }
110137
111138 /// <summary>
@@ -184,6 +211,11 @@ interface IStreamWriter : IDisposable
184211 /// IStreamReader.GotoSuffixLabel for more)
185212 /// </summary>
186213 void WriteSuffixLabel ( StreamLabel value ) ;
214+
215+ /// <summary>
216+ /// The settings associated with this writer.
217+ /// </summary>
218+ SerializationSettings Settings { get ; }
187219 }
188220
189221
@@ -253,6 +285,11 @@ interface IStreamReader : IDisposable
253285 /// and then seeking to that position.
254286 /// </summary>
255287 void GotoSuffixLabel ( ) ;
288+
289+ /// <summary>
290+ /// The settings associated with this reader.
291+ /// </summary>
292+ SerializationSettings Settings { get ; }
256293 }
257294
258295#if ! DOTNET_V35
@@ -516,7 +553,7 @@ sealed class Serializer : IDisposable
516553 /// <param name="filePath">The destination file.</param>
517554 /// <param name="entryObject">The object to serialize.</param>
518555 /// <param name="share">Optional sharing mode for the destination file. Defaults to <see cref="FileShare.Read"/>.</param>
519- public Serializer ( string filePath , IFastSerializable entryObject , FileShare share = FileShare . Read ) : this ( new IOStreamStreamWriter ( filePath , share : share ) , entryObject ) { }
556+ public Serializer ( string filePath , IFastSerializable entryObject , FileShare share = FileShare . Read ) : this ( new IOStreamStreamWriter ( filePath , settings : SerializationSettings . Default , share : share ) , entryObject ) { }
520557
521558 /// <summary>
522559 /// Create a serializer that writes <paramref name="entryObject"/> to a <see cref="Stream"/>. The serializer
@@ -533,7 +570,7 @@ public Serializer(Stream outputStream, IFastSerializable entryObject)
533570 /// closes.
534571 /// </summary>
535572 public Serializer ( Stream outputStream , IFastSerializable entryObject , bool leaveOpen )
536- : this ( new IOStreamStreamWriter ( outputStream , leaveOpen : leaveOpen ) , entryObject )
573+ : this ( new IOStreamStreamWriter ( outputStream , SerializationSettings . Default , leaveOpen : leaveOpen ) , entryObject )
537574 {
538575 }
539576
@@ -1035,18 +1072,18 @@ sealed class Deserializer : IDisposable
10351072 /// <summary>
10361073 /// Create a Deserializer that reads its data from a given file
10371074 /// </summary>
1038- public Deserializer ( string filePath , SerializationConfiguration config = null )
1075+ public Deserializer ( string filePath , SerializationSettings settings )
10391076 {
1040- IOStreamStreamReader reader = new IOStreamStreamReader ( filePath , config ) ;
1077+ IOStreamStreamReader reader = new IOStreamStreamReader ( filePath , settings ) ;
10411078 Initialize ( reader , filePath ) ;
10421079 }
10431080
10441081 /// <summary>
10451082 /// Create a Deserializer that reads its data from a given System.IO.Stream. The stream will be closed when the Deserializer is done with it.
10461083 /// </summary>
1047- public Deserializer ( Stream inputStream , string streamName , SerializationConfiguration config = null )
1084+ public Deserializer ( Stream inputStream , string streamName , SerializationSettings settings )
10481085 {
1049- IOStreamStreamReader reader = new IOStreamStreamReader ( inputStream , config : config ) ;
1086+ IOStreamStreamReader reader = new IOStreamStreamReader ( inputStream , settings : settings ) ;
10501087 Initialize ( reader , streamName ) ;
10511088 }
10521089
@@ -1055,9 +1092,9 @@ public Deserializer(Stream inputStream, string streamName, SerializationConfigur
10551092 /// <paramref name="leaveOpen"/> parameter determines whether the deserializer will close the stream when it
10561093 /// closes.
10571094 /// </summary>
1058- public Deserializer ( Stream inputStream , string streamName , bool leaveOpen , SerializationConfiguration config = null )
1095+ public Deserializer ( Stream inputStream , string streamName , bool leaveOpen , SerializationSettings settings )
10591096 {
1060- IOStreamStreamReader reader = new IOStreamStreamReader ( inputStream , leaveOpen : leaveOpen , config : config ) ;
1097+ IOStreamStreamReader reader = new IOStreamStreamReader ( inputStream , leaveOpen : leaveOpen , settings : settings ) ;
10611098 Initialize ( reader , streamName ) ;
10621099 }
10631100
@@ -1610,38 +1647,61 @@ public StreamLabel ResolveForwardReference(ForwardReference reference, bool pres
16101647 public String Name { get ; private set ; }
16111648
16121649 /// <summary>
1613- /// If set this function is set, then it is called whenever a type name from the serialization
1614- /// data is encountered. It is your you then need to look that up. If it is not present
1615- /// it uses Type.GetType(string) which only checks the current assembly and mscorlib.
1650+ /// Called when <code>Deserializer</code> encounters a type that is not registered, allowing the implementation
1651+ /// to return a factory delegate to be cached and used for subsequent encounters.
16161652 /// </summary>
1617- public Func < string , Type > TypeResolver { get ; set ; }
1653+ public Func < string , Func < IFastSerializable > > OnUnregisteredType { get ; set ; }
16181654
16191655 /// <summary>
1620- /// For every IFastSerializable object being deserialized, the Deserializer needs to create 'empty' objects
1621- /// that 'FromStream' is invoked on. The Deserializer gets these 'empty' objects by calling a 'factory'
1622- /// delegate for that type. Thus all types being deserialized must have a factory.
1656+ /// Registers a creation factory for a type.
16231657 ///
1624- /// RegisterFactory registers such a factory for particular 'type'.
1658+ /// When the <code>Deserializer</code>encounters a serialized type, it will look for a registered factory or type registration
1659+ /// so that it knows how to construct an empty instance of the type that can be filled. All non-primitive types
1660+ /// must either be registered by calling RegisterFactory or RegisterType.
16251661 /// </summary>
16261662 public void RegisterFactory ( Type type , Func < IFastSerializable > factory )
16271663 {
16281664 factories [ type . FullName ] = factory ;
16291665 }
1666+
1667+ /// <summary>
1668+ /// Registers a creation factory for a type name.
1669+ ///
1670+ /// When the <code>Deserializer</code>encounters a serialized type, it will look for a registered factory or type registration
1671+ /// so that it knows how to construct an empty instance of the type that can be filled. All non-primitive types
1672+ /// must either be registered by calling RegisterFactory or RegisterType.
1673+ /// </summary>
16301674 public void RegisterFactory ( string typeName , Func < IFastSerializable > factory )
16311675 {
16321676 factories [ typeName ] = factory ;
16331677 }
16341678
16351679 /// <summary>
1636- /// For every IFastSerializable object being deserialized, the Deserializer needs to create 'empty' objects
1637- /// that 'FromStream' is invoked on. The Deserializer gets these 'empty' objects by calling a 'factory'
1638- /// delegate for that type. Thus all types being deserialized must have a factory.
1680+ /// Registers a type that can be created by instantiating the parameterless constructor.
16391681 ///
1640- /// RegisterDefaultFactory registers a factory that is passed a type parameter and returns a new IFastSerialable object.
1682+ /// When the <code>Deserializer</code>encounters a serialized type, it will look for a registered factory or type registration
1683+ /// so that it knows how to construct an empty instance of the type that can be filled. All non-primitive types
1684+ /// must either be registered by calling RegisterFactory or RegisterType.
16411685 /// </summary>
1642- public void RegisterDefaultFactory ( Func < Type , IFastSerializable > defaultFactory )
1686+ public void RegisterType ( Type type )
1687+ {
1688+ RegisterFactory ( type , ( ) =>
1689+ {
1690+ return CreateDefault ( type ) ;
1691+ } ) ;
1692+ }
1693+
1694+ private static IFastSerializable CreateDefault ( Type type )
16431695 {
1644- this . defaultFactory = defaultFactory ;
1696+ try
1697+ {
1698+ return ( IFastSerializable ) Activator . CreateInstance ( type ) ;
1699+ }
1700+ catch ( MissingMethodException )
1701+ {
1702+ throw new SerializationException (
1703+ $ "Unable to create an object of type { type . FullName } . It must either have a parameterless constructor or have been registered with the deserializer via RegisterFactory.") ;
1704+ }
16451705 }
16461706
16471707 // For FromStream method bodies, reading tagged values (for post V1 field additions)
@@ -1964,49 +2024,31 @@ private IFastSerializable ReadObjectDefinition(Tags tag, StreamLabel objectLabel
19642024
19652025 internal Func < IFastSerializable > GetFactory ( string fullName )
19662026 {
1967- Func < IFastSerializable > ret ;
1968- if ( factories . TryGetValue ( fullName , out ret ) )
2027+ // Check for a registered factory.
2028+ Func < IFastSerializable > factory = null ;
2029+ if ( factories . TryGetValue ( fullName , out factory ) )
19692030 {
1970- return ret ;
2031+ return factory ;
19712032 }
19722033
1973- Type type ;
1974- if ( TypeResolver != null )
1975- {
1976- type = TypeResolver ( fullName ) ;
1977- }
1978- else
2034+ // If there is not a registered factory, give the implementation of IFastSerializable an opportunity to create a factory.
2035+ if ( OnUnregisteredType != null )
19792036 {
1980- type = Type . GetType ( fullName ) ;
2037+ factory = OnUnregisteredType ( fullName ) ;
2038+ if ( factory != null )
2039+ {
2040+ // Save the factory for future encounters of this type name.
2041+ RegisterFactory ( fullName , factory ) ;
2042+ }
19812043 }
19822044
1983- if ( type == null )
2045+ if ( factory == null )
19842046 {
1985- throw new TypeLoadException ( "Could not find type " + fullName ) ;
2047+ throw new TypeLoadException (
2048+ $ "Could not create an instance of type { fullName } . The type must be registered with the deserializer via a call to RegisterFactory or RegisterType.") ;
19862049 }
19872050
1988- return delegate
1989- {
1990- // If we have a default factory, use it.
1991- if ( defaultFactory != null )
1992- {
1993- IFastSerializable instance = defaultFactory ( type ) ;
1994- if ( instance != null )
1995- {
1996- return instance ;
1997- }
1998- }
1999- // Factory of last resort.
2000- try
2001- {
2002- return ( IFastSerializable ) Activator . CreateInstance ( type ) ;
2003- }
2004- catch ( MissingMethodException )
2005- {
2006- throw new SerializationException ( "Failure deserializing " + type . FullName +
2007- ".\r \n It must either have a parameterless constructor or been registered with the serializer." ) ;
2008- }
2009- } ;
2051+ return factory ;
20102052 }
20112053
20122054 private void FindEndTag ( SerializationType type , IFastSerializable objectBeingDeserialized )
@@ -2144,7 +2186,6 @@ private Tags ReadTag()
21442186 /// </summary>
21452187 internal bool deferForwardReferences ;
21462188 private Dictionary < string , Func < IFastSerializable > > factories ;
2147- private Func < Type , IFastSerializable > defaultFactory ;
21482189 #endregion
21492190 } ;
21502191
0 commit comments