akkadotnet / Hyperion

Polymorphic serialization for .NET
Apache License 2.0
278 stars 62 forks source link

spawne with actorbuilder would cause AmbiguousMatchException #198

Open ingted opened 3 years ago

ingted commented 3 years ago

Hi,

let deployRemotely address = Akka.Actor.Deploy(Akka.Actor.RemoteScope (Akka.Actor.Address.Parse address)) 
let spawnRemote systemOrContext remoteSystemAddress actorName expr otherOptionList =  
    Akka.FSharp.Spawn.spawne systemOrContext actorName expr ([Akka.FSharp.Spawn.SpawnOption.Deploy (deployRemotely remoteSystemAddress)] |> List.append otherOptionList)
let raddr = sprintf "akka.tcp://cluster-system@10.28.199.142:9000"
let actor9000 =
    spawnRemote system raddr ("remoteTest" + System.Guid.NewGuid().ToString())
        <@    
            fun (mailbox: Akka.FSharp.Actors.Actor<string>) ->
                let rec a () = Akka.FSharp.Actors.actor {
                    let! _msg = mailbox.Receive()
                    printfn "%s..." _msg
                    if false then
                        return ""
                    else
                        return! a()

                }
                a()
        @> [Akka.FSharp.Spawn.SpawnOption.SupervisorStrategy(Akka.FSharp.Strategy.OneForOne(fun error ->
            match error with
            | _ -> Akka.Actor.Directive.Resume
            ))]

spawne with a remote deployment would cause AmbiguousMatchException:

System.Reflection.AmbiguousMatchException: More than one matching method found!
   at Hyperion.Extensions.TypeEx.GetMethodExt(MethodInfo& matchingMethod, Type type, String name, BindingFlags bindingFlags, Type[] parameterTypes)
   at Hyperion.Extensions.TypeEx.GetMethodExt(Type thisType, String name, BindingFlags bindingFlags, Type[] parameterTypes)

image

(Because Cont<> has two union cases)

Could anyone provide a hint about how to get a workaround? Thank you!

ingted commented 3 years ago

My currently workaround:

                    if (i == parameterInfos.Length)
                    {

                        if (matchingMethod == null)
                            matchingMethod = methodInfo;
                        else
                        {
                            if (mbrs.Length == 2)
                            {
                                try
                                {
                                    var mbr0 = (MethodInfo)mbrs[0];
                                    var mbr1 = (MethodInfo)mbrs[1];
                                    var p0 = mbr0.GetParameters()[0].ParameterType;
                                    var p1 = mbr1.GetParameters()[0].ParameterType;
                                    var p0nm = p0.Name;
                                    var p1nm = p1.Name;
                                    var p0gt0 = p0.GenericTypeArguments[0].Name;
                                    var p0gt1 = p0.GenericTypeArguments[1].Name;
                                    if (p0nm == "FSharpFunc`2" && p1nm == "Cont`2" && p0gt0 == "Unit" && p0gt1 == "Cont`2") { }
                                    else
                                    {
                                        throw new AmbiguousMatchException(
                                            "More than one matching method found0!");
                                    }
                                }
                                catch
                                {
                                    throw new AmbiguousMatchException(
                                            "More than one matching method found1!");
                                }
                            }
                            else
                            {

                                throw new AmbiguousMatchException(
                                    "More than one matching method found!");
                            }
                        }
                    }

use if (p0nm == "FSharpFunc2" && p1nm == "Cont2" && p0gt0 == "Unit" && p0gt1 == "Cont`2") { } to avoid exception

ingted commented 3 years ago

Hi @Horusiath, do you think this would cover all spawne quotation expression cases?

ingted commented 3 years ago

I found this will not work for complex quotation... image