FsPickler icon indicating copy to clipboard operation
FsPickler copied to clipboard

Migration to another serialization library

Open ingted opened this issue 1 year ago • 0 comments

Hi!

For those one who wants to migrate to another lib and you found that old serialized data not working now, here is a workaround:

Modify loadMemberInfo to force to assign a type name mapped to make assembly.GetType silent.

assembly.GetType(TypeMap.GetAlternativeName(assembly.FullName, tIP.Name), throwOnError = true) |> 

type TypeMap () =

    // 靜態 ConcurrentDictionary 映射 Assembly 和名稱對應的替代名稱
    static let typeMap = ConcurrentDictionary<string, ConcurrentDictionary<string, string>>()

    /// 新增或更新 Assembly 和 Name 對應的替代名稱
    static member AddOrUpdateAlternativeName(assembly: string, name: string, altName: string) =
        let nameMap = typeMap.GetOrAdd(assembly, fun _ -> ConcurrentDictionary<string, string>())
        nameMap.AddOrUpdate(name, altName, fun _ _ -> altName) |> ignore

    /// 根據 Assembly 和 Name 取得替代名稱,如果不存在則回傳原始名稱
    static member GetAlternativeName(assembly: string, name: string) =
        match typeMap.TryGetValue(assembly) with
        | true, nameMap ->
            match nameMap.TryGetValue(name) with
            | true, altName -> altName
            | false, _ -> name
        | false, _ -> name


let loadMemberInfo (tyConv : ITypeNameConverter option) 
                    (getAssembly : bool -> AssemblyInfo -> Assembly) 
                    (getMethodSignature : MethodInfo -> string) 
                    (enableAssemblyLoading : bool) (mI : CompositeMemberInfo) =

    let inline getFlags isStatic =
        let allVisibility = BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.FlattenHierarchy
        allVisibility ||| (if isStatic then BindingFlags.Static else BindingFlags.Instance)

    match mI with
    | NamedType(name, aI) ->
        printfn "NamedType: Name = %A, AssemblyInfo = %A" name aI
        let tI = { Name = name ; AssemblyInfo = aI }
        let tIP =
            match tyConv with
            | None -> tI
            | Some tc -> tc.ToDeserializedType tI

        let assembly = getAssembly enableAssemblyLoading tIP.AssemblyInfo
        assembly.GetType(TypeMap.GetAlternativeName(assembly.FullName, tIP.Name), throwOnError = true) |> fastUnbox<MemberInfo>

Of course you need to use dotPeek (etc...) to check the type mapping between new and old libraries and do stuffs like

TypeMap.AddOrUpdateAlternativeName(ass2.FullName, "FAkka.TA.TAType+-ctor@200-11", "FAkka.TA.TAType+-ctor@200-11")
TypeMap.AddOrUpdateAlternativeName(ass2.FullName, "FAkka.TA.TAType+-ctor@208-12", "FAkka.TA.TAType+-ctor@210-12")
TypeMap.AddOrUpdateAlternativeName(ass2.FullName, "FAkka.TA.TAType+-ctor@216-13", "FAkka.TA.TAType+-ctor@220-13")
TypeMap.AddOrUpdateAlternativeName(ass2.FullName, "FAkka.TA.TAType+-ctor@224-14", "FAkka.TA.TAType+-ctor@230-14")
TypeMap.AddOrUpdateAlternativeName(ass2.FullName, "FAkka.TA.TAType+-ctor@232-15", "FAkka.TA.TAType+-ctor@240-15")
TypeMap.AddOrUpdateAlternativeName(ass2.FullName, "FAkka.TA.TAType+-ctor@240-16", "FAkka.TA.TAType+-ctor@248-16")
TypeMap.AddOrUpdateAlternativeName(ass2.FullName, "FAkka.TA.TAType+-ctor@640-17<SLKey, SLTAKey, KeyOfSL>", "FAkka.TA.TAType+-ctor@648-17<SLKey, SLTAKey, KeyOfSL>")

Before FsPickler start to work.

ingted avatar Nov 07 '24 00:11 ingted