diff --git a/src/FsPickler/FsPickler/FsPickler.fs b/src/FsPickler/FsPickler/FsPickler.fs index 20a32a22..5f5c3f2a 100644 --- a/src/FsPickler/FsPickler/FsPickler.fs +++ b/src/FsPickler/FsPickler/FsPickler.fs @@ -31,11 +31,16 @@ type FsPickler private () = static member CreateXmlSerializer([]?typeConverter : ITypeNameConverter, []?indent : bool, [] ?picklerResolver : IPicklerResolver) = new XmlSerializer(?typeConverter = typeConverter, ?indent = indent, ?picklerResolver = picklerResolver) - /// Decides if given type is serializable by FsPickler + /// + /// Decides if given type is serializable by FsPickler + /// static member IsSerializableType<'T> () : bool = resolver().IsSerializable<'T> () - /// Decides if given type is serializable by FsPickler + /// + /// Decides if given type is serializable by FsPickler + /// + /// Type to be checked. static member IsSerializableType (t : Type) : bool = resolver().IsSerializable t @@ -48,11 +53,16 @@ type FsPickler private () = try FsPickler.EnsureSerializable(graph, ?failOnCloneableOnlyTypes = failOnCloneableOnlyTypes) ; true with :? FsPicklerException -> false - /// Auto generates a pickler for given type variable + /// + /// Auto generates a pickler for given type variable + /// static member GeneratePickler<'T> () : Pickler<'T> = resolver().Resolve<'T> () - - /// Auto generates a pickler for given type + + /// + /// Auto generates a pickler for given type + /// + /// Type for which pickler will be generated. static member GeneratePickler (t : Type) : Pickler = resolver().Resolve t @@ -69,8 +79,20 @@ type FsPickler private () = /// Pickler used for cloning. Defaults to auto-generated pickler. /// Streaming context used for cloning. Defaults to null streaming context. static member Clone<'T> (value : 'T, []?pickler : Pickler<'T>, []?streamingContext : StreamingContext) : 'T = - let pickler = match pickler with None -> resolver().Resolve<'T> () | Some p -> p - let state = new CloneState(resolver(), ?streamingContext = streamingContext) + FsPickler.Clone(value, resolver(), ?pickler = pickler, ?streamingContext = streamingContext) + + /// + /// Performs an in-memory, deep cloning of provided serializable object graph. + /// Cloning is performed on a node-to-node basis and does not make use of intermediate + /// serialization buffers. + /// + /// Value to be cloned. + /// Specify a custom pickler resolver/cache for serialization. + /// Pickler used for cloning. Defaults to auto-generated pickler. + /// Streaming context used for cloning. Defaults to null streaming context. + static member Clone<'T> (value : 'T, picklerResolver : IPicklerResolver, []?pickler : Pickler<'T>, []?streamingContext : StreamingContext) : 'T = + let pickler = match pickler with None -> picklerResolver.Resolve<'T> () | Some p -> p + let state = new CloneState(picklerResolver, ?streamingContext = streamingContext) pickler.Clone state value /// @@ -83,8 +105,21 @@ type FsPickler private () = /// Streaming context used for cloning. Defaults to null streaming context. /// A sifted wrapper together with all objects that have been sifted. static member Sift<'T>(value : 'T, sifter : IObjectSifter, []?pickler : Pickler<'T>, []?streamingContext : StreamingContext) : Sifted<'T> * (int64 * obj) [] = - let pickler = match pickler with None -> resolver().Resolve<'T> () | Some p -> p - let state = new CloneState(resolver(), ?streamingContext = streamingContext, sifter = sifter) + FsPickler.Sift(value, sifter, resolver(), ?pickler = pickler, ?streamingContext = streamingContext) + + /// + /// Creates a clone of the provided object graph, sifting objects from the graph as specified by the provided sifter implementation. + /// Only reference types can be sifted from a graph. + /// + /// Value to be sifted. + /// Sifting predicate implementation. + /// Specify a custom pickler resolver/cache for serialization. + /// Pickler to be used for traversal. Defaults to auto-generated pickler. + /// Streaming context used for cloning. Defaults to null streaming context. + /// A sifted wrapper together with all objects that have been sifted. + static member Sift<'T>(value : 'T, sifter : IObjectSifter, picklerResolver : IPicklerResolver, []?pickler : Pickler<'T>, []?streamingContext : StreamingContext) : Sifted<'T> * (int64 * obj) [] = + let pickler = match pickler with None -> picklerResolver.Resolve<'T> () | Some p -> p + let state = new CloneState(picklerResolver, ?streamingContext = streamingContext, sifter = sifter) let sifted = pickler.Clone state value state.CreateSift(sifted) @@ -98,8 +133,21 @@ type FsPickler private () = /// Streaming context used for cloning. Defaults to null streaming context. /// A sifted wrapper together with all objects that have been sifted. static member Sift<'T>(value : 'T, sifter : obj -> bool, []?pickler : Pickler<'T>, []?streamingContext : StreamingContext) : Sifted<'T> * (int64 * obj) [] = + FsPickler.Sift(value, sifter, resolver(), ?pickler = pickler, ?streamingContext = streamingContext) + + /// + /// Creates a clone of the provided object graph, sifting objects from the graph as specified by the provided sifter implementation. + /// Only reference types can be sifted from a graph. + /// + /// Value to be sifted. + /// Sifting predicate implementation. + /// Specify a custom pickler resolver/cache for serialization. + /// Pickler to be used for traversal. Defaults to auto-generated pickler. + /// Streaming context used for cloning. Defaults to null streaming context. + /// A sifted wrapper together with all objects that have been sifted. + static member Sift<'T>(value : 'T, sifter : obj -> bool, picklerResolver : IPicklerResolver, []?pickler : Pickler<'T>, []?streamingContext : StreamingContext) : Sifted<'T> * (int64 * obj) [] = let sifter = { new IObjectSifter with member __.Sift(_,_,t) = sifter t } - FsPickler.Sift(value, sifter, ?pickler = pickler, ?streamingContext = streamingContext) + FsPickler.Sift(value, sifter, picklerResolver, ?pickler = pickler, ?streamingContext = streamingContext) /// /// Unsifts a provided object graph with given values. @@ -114,6 +162,20 @@ type FsPickler private () = let state = new CloneState(resolver(), ?streamingContext = streamingContext, unSiftData = (values, sifted.SiftedIndices)) pickler.Clone state sifted.Value + /// + /// Unsifts a provided object graph with given values. + /// + /// Sifted object graph to be unsifted. + /// Values to be pushed in sift holes. + /// Specify a custom pickler resolver/cache for serialization. + /// Pickler to be used for traversal. Defaults to auto-generated pickler. + /// Streaming context used for cloning. Defaults to null streaming context. + /// An unsifted object graph. + static member UnSift<'T>(sifted : Sifted<'T>, values:(int64 * obj) [], picklerResolver : IPicklerResolver, []?pickler : Pickler<'T>, []?streamingContext : StreamingContext) : 'T = + let pickler = match pickler with None -> picklerResolver.Resolve<'T> () | Some p -> p + let state = new CloneState(picklerResolver, ?streamingContext = streamingContext, unSiftData = (values, sifted.SiftedIndices)) + pickler.Clone state sifted.Value + /// Compute size in bytes for given input. /// input value. /// Pickler to be used for size computation. Defaults to auto-generated pickler. @@ -137,10 +199,21 @@ type FsPickler private () = /// Object graph traversal order. Defaults to pre-order traversal. static member VisitObject(visitor : IObjectVisitor, graph : 'T, []?pickler:Pickler<'T>, []?streamingContext:StreamingContext, []?visitOrder:VisitOrder) = + FsPickler.VisitObject(visitor, graph, resolver(), ?streamingContext = streamingContext, ?visitOrder = visitOrder) - let resolver = resolver() - let pickler = match pickler with None -> resolver.Resolve<'T> () | Some p -> p - let state = new VisitState(resolver, visitor, ?streamingContext = streamingContext, ?visitOrder = visitOrder) + /// + /// Visits all reference types that appear in the given object graph. + /// + /// Visitor implementation. + /// Object graph. + /// Specify a custom pickler resolver/cache for serialization. + /// Pickler to be used for traversal. Defaults to auto-generated pickler. + /// Streaming context used for cloning. Defaults to null streaming context. + /// Object graph traversal order. Defaults to pre-order traversal. + static member VisitObject(visitor : IObjectVisitor, graph : 'T, picklerResolver : IPicklerResolver, []?pickler:Pickler<'T>, + []?streamingContext:StreamingContext, []?visitOrder:VisitOrder) = + let pickler = match pickler with None -> picklerResolver.Resolve<'T> () | Some p -> p + let state = new VisitState(picklerResolver, visitor, ?streamingContext = streamingContext, ?visitOrder = visitOrder) pickler.Accept state graph /// Compute size and hashcode for given input. @@ -154,6 +227,14 @@ type FsPickler private () = /// /// input object graph. static member GatherTypesInObjectGraph(graph : obj) : Type [] = + FsPickler.GatherTypesInObjectGraph(graph, resolver()) + + /// + /// Uses FsPickler to traverse the object graph, gathering types of objects as it goes. + /// + /// input object graph. + /// Specify a custom pickler resolver/cache for serialization. + static member GatherTypesInObjectGraph(graph : obj, picklerResolver : IPicklerResolver) : Type [] = let gathered = new HashSet () let visitor = { @@ -179,7 +260,7 @@ type FsPickler private () = true // always continue traversal } - do FsPickler.VisitObject(visitor, graph) + do FsPickler.VisitObject(visitor, graph, picklerResolver) gathered |> Seq.toArray /// @@ -187,6 +268,14 @@ type FsPickler private () = /// /// input object graph. static member GatherObjectsInGraph (graph : obj) : obj [] = + FsPickler.GatherObjectsInGraph(graph, resolver()) + + /// + /// Use FsPickler to traverse the object graph, gathering object instances as it goes. + /// + /// input object graph. + /// Specify a custom pickler resolver/cache for serialization. + static member GatherObjectsInGraph (graph : obj, picklerResolver : IPicklerResolver) : obj [] = let gathered = new HashSet () let visitor = { @@ -201,16 +290,24 @@ type FsPickler private () = true // continue traversal } - do FsPickler.VisitObject(visitor, graph) + do FsPickler.VisitObject(visitor, graph, picklerResolver) gathered |> Seq.toArray - /// /// Traverses the object graph, completing if serializable or raising a serialization exception if not. /// /// Graph to be checked. /// Fail on types that are declared cloneable only. Defaults to true. static member EnsureSerializable (graph : 'T, [] ?failOnCloneableOnlyTypes : bool) : unit = + FsPickler.EnsureSerializable(graph, resolver(), ?failOnCloneableOnlyTypes = failOnCloneableOnlyTypes) + + /// + /// Traverses the object graph, completing if serializable or raising a serialization exception if not. + /// + /// Graph to be checked. + /// Specify a custom pickler resolver/cache for serialization. + /// Fail on types that are declared cloneable only. Defaults to true. + static member EnsureSerializable (graph : 'T, picklerResolver : IPicklerResolver, [] ?failOnCloneableOnlyTypes : bool) : unit = let failOnCloneableOnlyTypes = defaultArg failOnCloneableOnlyTypes true let visitor = { new IObjectVisitor with @@ -220,4 +317,4 @@ type FsPickler private () = else true } - FsPickler.VisitObject(visitor, graph, visitOrder = VisitOrder.PreOrder) \ No newline at end of file + FsPickler.VisitObject(visitor, graph, picklerResolver, visitOrder = VisitOrder.PreOrder) \ No newline at end of file