From 1deb5518f7b34581ea752e39062d912af0db88d1 Mon Sep 17 00:00:00 2001 From: KasperSK Date: Fri, 25 Sep 2020 15:25:43 +0200 Subject: [PATCH 1/3] First implementation can select different overloads --- .../ActionMessageTests.cs | 59 +++++++++++++++++++ src/Caliburn.Micro.Platform/ActionMessage.cs | 27 +++++++-- 2 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 src/Caliburn.Micro.Platform.Tests/ActionMessageTests.cs diff --git a/src/Caliburn.Micro.Platform.Tests/ActionMessageTests.cs b/src/Caliburn.Micro.Platform.Tests/ActionMessageTests.cs new file mode 100644 index 000000000..365e95530 --- /dev/null +++ b/src/Caliburn.Micro.Platform.Tests/ActionMessageTests.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Xunit; + +namespace Caliburn.Micro.Platform.Tests +{ + public class ActionMessageTests + { + + [Fact] + public void GetMethodPicksOverLoad() + { + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + am.Parameters.Add(new Parameter(){ Value = "2"}); + var obj = new Overloads(); + + + var result = ActionMessage.GetTargetMethod(am, obj); + } + + class Overloads + { + public void Overloaded(int s) + { + + } + + public void Overloaded(string s) + { + + } + + public void Overloaded(Bar s) + { + + } + + public void Overloaded(Foo s) + { + + } + } + + class Foo + { + + } + + class Bar : Foo + { + + } + } +} diff --git a/src/Caliburn.Micro.Platform/ActionMessage.cs b/src/Caliburn.Micro.Platform/ActionMessage.cs index 8d7e043ef..47cf60a69 100644 --- a/src/Caliburn.Micro.Platform/ActionMessage.cs +++ b/src/Caliburn.Micro.Platform/ActionMessage.cs @@ -380,11 +380,28 @@ public override string ToString() { where message.Parameters.Count == methodParameters.Length select method).FirstOrDefault(); #else - return (from method in target.GetType().GetMethods() - where method.Name == message.MethodName - let methodParameters = method.GetParameters() - where message.Parameters.Count == methodParameters.Length - select method).FirstOrDefault(); + //return + + var methods = (from method in target.GetType().GetMethods() + where method.Name == message.MethodName + let methodParameters = method.GetParameters() + where message.Parameters.Count == methodParameters.Length && message.Parameters.Zip(methodParameters, + (parameter, info) => info.ParameterType.IsInstanceOfType(parameter.Value)).All(b => b) + select method); + + MethodInfo returnMethodInfo = null; + foreach (MethodInfo method in methods) + { + returnMethodInfo = method; + if (method.GetParameters().Zip(message.Parameters, (info, parameter) => + parameter.Value.GetType().IsAssignableFrom(info.ParameterType) + ).All(b => b)) + { + break; + } + } + + return returnMethodInfo; #endif }; From 47dd9a8654193675994c3c1932ce8393f02ac9f2 Mon Sep 17 00:00:00 2001 From: KasperSK Date: Thu, 28 Jan 2021 14:39:32 +0100 Subject: [PATCH 2/3] Enable action message to pick method based on parameters and their type --- .../ActionMessageTests.cs | 334 +++++++++++++++++- src/Caliburn.Micro.Platform/ActionMessage.cs | 48 ++- .../Platforms/Xamarin.Forms/ActionMessage.cs | 30 +- 3 files changed, 390 insertions(+), 22 deletions(-) diff --git a/src/Caliburn.Micro.Platform.Tests/ActionMessageTests.cs b/src/Caliburn.Micro.Platform.Tests/ActionMessageTests.cs index 365e95530..bed5f84eb 100644 --- a/src/Caliburn.Micro.Platform.Tests/ActionMessageTests.cs +++ b/src/Caliburn.Micro.Platform.Tests/ActionMessageTests.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; +using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; @@ -10,22 +12,293 @@ namespace Caliburn.Micro.Platform.Tests { public class ActionMessageTests { + [Fact] + public void GetMethodPicksOverLoadStructParameter() + { + //Arrange + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + + am.Parameters.Add(new Parameter() { Value = 1 }); + am.Parameters.Add(new Parameter() { Value = 1 }); + var obj = new Overloads(); + + var expected = MethodInfoHelper.GetMethodInfo(o => o.Overloaded(1, 1)); + + //Act + var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } + + [Fact] + public void GetMethodPicksOverLoadStructStringParameter() + { + //Arrange + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + + am.Parameters.Add(new Parameter() { Value = 1 }); + am.Parameters.Add(new Parameter() { Value = 1 }); + am.Parameters.Add(new Parameter() { Value = "" }); + var obj = new Overloads(); + + var expected = MethodInfoHelper.GetMethodInfo(o => o.Overloaded(1, 1, "")); + + //Act + var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } + + [Fact] + public void GetMethodPicksOverLoadStringParameter() + { + //Arrange + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + + am.Parameters.Add(new Parameter() { Value = "" }); + am.Parameters.Add(new Parameter() { Value = "" }); + var obj = new Overloads(); + + var expected = MethodInfoHelper.GetMethodInfo(o => o.Overloaded("", "")); + + //Act + var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } + + [Fact] + public void GetMethodPicksOverLoadStringStructParameter() + { + //Arrange + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + + am.Parameters.Add(new Parameter() { Value = "" }); + am.Parameters.Add(new Parameter() { Value = "" }); + am.Parameters.Add(new Parameter() { Value = 1 }); + var obj = new Overloads(); + + var expected = MethodInfoHelper.GetMethodInfo(o => o.Overloaded("", "", 1)); + + //Act + var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } + + [Fact] + public void GetMethodPicksOverLoadTwoDifferntParameter() + { + //Arrange + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + + am.Parameters.Add(new Parameter() { Value = new Foo() }); + am.Parameters.Add(new Parameter() { Value = new Bar() }); + var obj = new Overloads(); + + var expected = MethodInfoHelper.GetMethodInfo(o => o.Overloaded(new Foo(), new Bar())); + + //Act + var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } + + [Fact] + public void GetMethodPicksOverLoadTwoBaseParameter() + { + //Arrange + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + + am.Parameters.Add(new Parameter() { Value = new Foo() }); + am.Parameters.Add(new Parameter() { Value = new Foo() }); + var obj = new Overloads(); + + var expected = MethodInfoHelper.GetMethodInfo(o => o.Overloaded(new Foo(), new Foo())); + + //Act + var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } + + [Fact] + public void GetMethodPicksOverLoadTwoDerivedParameter() + { + //Arrange + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + + am.Parameters.Add(new Parameter() { Value = new Bar() }); + am.Parameters.Add(new Parameter() { Value = new Bar() }); + var obj = new Overloads(); + + var expected = MethodInfoHelper.GetMethodInfo(o => o.Overloaded(new Bar(), new Bar())); + + //Act + var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } + + [Fact] + public void GetMethodPicksOverLoadEnumParameter() + { + //Arrange + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + + am.Parameters.Add(new Parameter() { Value = OverloadEnum.One }); + var obj = new Overloads(); + + var expected = MethodInfoHelper.GetMethodInfo(o => o.Overloaded(OverloadEnum.One)); + + //Act + var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } + + [Fact] + public void GetMethodPicksOverLoadDerivedOnlyParameter() + { + //Arrange + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + + am.Parameters.Add(new Parameter() { Value = new Bar() }); + am.Parameters.Add(new Parameter() { Value = new Bar() }); + var obj = new OverloadsDerivedOnly(); + + var expected = MethodInfoHelper.GetMethodInfo(o => o.Overloaded(new Bar(), new Bar())); + + //Act + var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } + + [Fact] + public void GetMethodPicksOverLoadDerivedOnlyBaseParameter() + { + //Arrange + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + + am.Parameters.Add(new Parameter() { Value = new Foo() }); + am.Parameters.Add(new Parameter() { Value = new Bar() }); + var obj = new OverloadsDerivedOnly(); + + MethodInfo expected = null; + + //Act + var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } + + + [Fact] + public void GetMethodPicksOverLoadBaseOnlyParameter() + { + //Arrange + var am = new ActionMessage(); + am.MethodName = "Overloaded"; + + am.Parameters.Add(new Parameter() { Value = new Bar() }); + am.Parameters.Add(new Parameter() { Value = new Bar() }); + var obj = new OverloadsBaseOnly(); + + var expected = MethodInfoHelper.GetMethodInfo(o => o.Overloaded(new Foo(), new Foo())); + + //Act + var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } [Fact] - public void GetMethodPicksOverLoad() + public void GetMethodPicksOverLoadBaseOnlyBaseParameter() { + //Arrange var am = new ActionMessage(); am.MethodName = "Overloaded"; - am.Parameters.Add(new Parameter(){ Value = "2"}); - var obj = new Overloads(); + am.Parameters.Add(new Parameter() { Value = new Foo() }); + am.Parameters.Add(new Parameter() { Value = new Bar() }); + var obj = new OverloadsBaseOnly(); + + MethodInfo expected = MethodInfoHelper.GetMethodInfo(o => o.Overloaded(new Foo(), new Foo())); + ; + //Act var result = ActionMessage.GetTargetMethod(am, obj); + + //Assert + Assert.Equal(result, expected); + } + + enum OverloadEnum + { + One,Two,Three + } + + class OverloadsBaseOnly + { + public void Overloaded(Foo f) + { + + } + + public void Overloaded(Foo f, Foo f2) + { + + } + } + + class OverloadsDerivedOnly + { + public void Overloaded(Bar b) + { + + } + + public void Overloaded(Bar b, Bar b2) + { + + } } class Overloads { - public void Overloaded(int s) + public void Overloaded(int i) + { + + } + + public void Overloaded(int i, int i2) + { + + } + + public void Overloaded(int i, int i2, string s) { } @@ -35,12 +308,47 @@ public void Overloaded(string s) } - public void Overloaded(Bar s) + public void Overloaded(string s, string s2) + { + + } + + public void Overloaded(string s, string s2, int i) + { + + } + + public void Overloaded(Foo F) + { + + } + + public void Overloaded(Bar B) { } - public void Overloaded(Foo s) + public void Overloaded(OverloadEnum E) + { + + } + + public void Overloaded(Foo s, Foo f) + { + + } + + public void Overloaded(Foo s, Bar b) + { + + } + + public void Overloaded(Bar s, Bar b) + { + + } + + public void Overloaded(Bar s, Foo f) { } @@ -56,4 +364,18 @@ class Bar : Foo } } + + public static class MethodInfoHelper + { + public static MethodInfo GetMethodInfo(Expression> expression) + { + var member = expression.Body as MethodCallExpression; + + if (member != null) + return member.Method; + + throw new ArgumentException("Expression is not a method", "expression"); + } + + } } diff --git a/src/Caliburn.Micro.Platform/ActionMessage.cs b/src/Caliburn.Micro.Platform/ActionMessage.cs index 47cf60a69..2a44d8c3a 100644 --- a/src/Caliburn.Micro.Platform/ActionMessage.cs +++ b/src/Caliburn.Micro.Platform/ActionMessage.cs @@ -374,20 +374,46 @@ public override string ToString() { /// The matching method, if available. public static Func GetTargetMethod = (message, target) => { #if WINDOWS_UWP - return (from method in target.GetType().GetRuntimeMethods() - where method.Name == message.MethodName - let methodParameters = method.GetParameters() - where message.Parameters.Count == methodParameters.Length - select method).FirstOrDefault(); + //return (from method in target.GetType().GetRuntimeMethods() + // where method.Name == message.MethodName + // let methodParameters = method.GetParameters() + // where message.Parameters.Count == methodParameters.Length + // select method).FirstOrDefault(); + + var methods = (from method in target.GetType().GetRuntimeMethods() + where method.Name == message.MethodName + let methodParameters = method.GetParameters() + where message.Parameters.Count == methodParameters.Length && message.Parameters.OfType().Zip(methodParameters, + (Parameter parameter, ParameterInfo info) => info.ParameterType.IsInstanceOfType(parameter.Value)).All(b => b) + select method); + + MethodInfo returnMethodInfo = null; + foreach (MethodInfo method in methods) + { + returnMethodInfo = method; + if (method.GetParameters().Zip(message.Parameters.OfType(), (info, parameter) => + parameter.Value.GetType().IsAssignableFrom(info.ParameterType) + ).All(b => b)) + { + break; + } + } + + return returnMethodInfo; + #else - //return + //return (from method in target.GetType().GetMethods() + //where method.Name == message.MethodName + //let methodParameters = method.GetParameters() + //where message.Parameters.Count == methodParameters.Length + //select method).FirstOrDefault(); var methods = (from method in target.GetType().GetMethods() - where method.Name == message.MethodName - let methodParameters = method.GetParameters() - where message.Parameters.Count == methodParameters.Length && message.Parameters.Zip(methodParameters, - (parameter, info) => info.ParameterType.IsInstanceOfType(parameter.Value)).All(b => b) - select method); + where method.Name == message.MethodName + let methodParameters = method.GetParameters() + where message.Parameters.Count == methodParameters.Length && message.Parameters.Zip(methodParameters, + (parameter, info) => info.ParameterType.IsInstanceOfType(parameter.Value)).All(b => b) + select method); MethodInfo returnMethodInfo = null; foreach (MethodInfo method in methods) diff --git a/src/Caliburn.Micro.Platform/Platforms/Xamarin.Forms/ActionMessage.cs b/src/Caliburn.Micro.Platform/Platforms/Xamarin.Forms/ActionMessage.cs index 7d108f782..31013a232 100644 --- a/src/Caliburn.Micro.Platform/Platforms/Xamarin.Forms/ActionMessage.cs +++ b/src/Caliburn.Micro.Platform/Platforms/Xamarin.Forms/ActionMessage.cs @@ -313,11 +313,31 @@ public override string ToString() /// The matching method, if available. public static Func GetTargetMethod = (message, target) => { - return (from method in target.GetType().GetRuntimeMethods() - where method.Name == message.MethodName - let methodParameters = method.GetParameters() - where message.Parameters.Count == methodParameters.Length - select method).FirstOrDefault(); + //return (from method in target.GetType().GetRuntimeMethods() + // where method.Name == message.MethodName + // let methodParameters = method.GetParameters() + // where message.Parameters.Count == methodParameters.Length + // select method).FirstOrDefault(); + var methods = (from method in target.GetType().GetRuntimeMethods() + where method.Name == message.MethodName + let methodParameters = method.GetParameters() + where message.Parameters.Count == methodParameters.Length && message.Parameters.OfType().Zip(methodParameters, + (parameter, info) => info.ParameterType.IsInstanceOfType(parameter.Value)).All(b => b) + select method); + + MethodInfo returnMethodInfo = null; + foreach (MethodInfo method in methods) + { + returnMethodInfo = method; + if (method.GetParameters().Zip(message.Parameters.OfType(), (info, parameter) => + parameter.Value.GetType().IsAssignableFrom(info.ParameterType) + ).All(b => b)) + { + break; + } + } + + return returnMethodInfo; }; /// From ba1cfa537d18edcc3f4bed4e4cbf065079cf6ef3 Mon Sep 17 00:00:00 2001 From: KasperSK Date: Fri, 29 Jan 2021 14:16:42 +0100 Subject: [PATCH 3/3] Added parameter check to when resolving guard methods --- src/Caliburn.Micro.Platform/ActionMessage.cs | 110 +++++++++--------- .../Platforms/Xamarin.Forms/ActionMessage.cs | 53 ++++----- 2 files changed, 79 insertions(+), 84 deletions(-) diff --git a/src/Caliburn.Micro.Platform/ActionMessage.cs b/src/Caliburn.Micro.Platform/ActionMessage.cs index 2a44d8c3a..18963e089 100644 --- a/src/Caliburn.Micro.Platform/ActionMessage.cs +++ b/src/Caliburn.Micro.Platform/ActionMessage.cs @@ -373,62 +373,7 @@ public override string ToString() { /// /// The matching method, if available. public static Func GetTargetMethod = (message, target) => { -#if WINDOWS_UWP - //return (from method in target.GetType().GetRuntimeMethods() - // where method.Name == message.MethodName - // let methodParameters = method.GetParameters() - // where message.Parameters.Count == methodParameters.Length - // select method).FirstOrDefault(); - - var methods = (from method in target.GetType().GetRuntimeMethods() - where method.Name == message.MethodName - let methodParameters = method.GetParameters() - where message.Parameters.Count == methodParameters.Length && message.Parameters.OfType().Zip(methodParameters, - (Parameter parameter, ParameterInfo info) => info.ParameterType.IsInstanceOfType(parameter.Value)).All(b => b) - select method); - - MethodInfo returnMethodInfo = null; - foreach (MethodInfo method in methods) - { - returnMethodInfo = method; - if (method.GetParameters().Zip(message.Parameters.OfType(), (info, parameter) => - parameter.Value.GetType().IsAssignableFrom(info.ParameterType) - ).All(b => b)) - { - break; - } - } - - return returnMethodInfo; - -#else - //return (from method in target.GetType().GetMethods() - //where method.Name == message.MethodName - //let methodParameters = method.GetParameters() - //where message.Parameters.Count == methodParameters.Length - //select method).FirstOrDefault(); - - var methods = (from method in target.GetType().GetMethods() - where method.Name == message.MethodName - let methodParameters = method.GetParameters() - where message.Parameters.Count == methodParameters.Length && message.Parameters.Zip(methodParameters, - (parameter, info) => info.ParameterType.IsInstanceOfType(parameter.Value)).All(b => b) - select method); - - MethodInfo returnMethodInfo = null; - foreach (MethodInfo method in methods) - { - returnMethodInfo = method; - if (method.GetParameters().Zip(message.Parameters, (info, parameter) => - parameter.Value.GetType().IsAssignableFrom(info.ParameterType) - ).All(b => b)) - { - break; - } - } - - return returnMethodInfo; -#endif + return GetMethodInfo(target.GetType(), message.MethodName, message); }; /// @@ -495,7 +440,7 @@ public override string ToString() { foreach (string possibleGuardName in possibleGuardNames) { matchingGuardName = possibleGuardName; - guard = GetMethodInfo(targetType, "get_" + matchingGuardName); + guard = GetMethodInfo(targetType, "get_" + matchingGuardName, context.Message); if (guard != null) break; } @@ -543,7 +488,7 @@ static MethodInfo TryFindGuardMethod(ActionExecutionContext context, IEnumerable MethodInfo guard = null; foreach (string possibleGuardName in possibleGuardNames) { - guard = GetMethodInfo(targetType, possibleGuardName); + guard = GetMethodInfo(targetType, possibleGuardName, context.Message); if (guard != null) break; } @@ -597,6 +542,55 @@ static MethodInfo GetMethodInfo(Type t, string methodName) return t.GetRuntimeMethods().SingleOrDefault(m => m.Name == methodName); #else return t.GetMethod(methodName); +#endif + } + + static MethodInfo GetMethodInfo(Type t, string methodName, ActionMessage message) + { +#if WINDOWS_UWP + var methods = (from method in t.GetRuntimeMethods() + where method.Name == methodName + let methodParameters = method.GetParameters() + where message.Parameters.Count == methodParameters.Length + && message.Parameters.OfType().Zip(methodParameters, + (parameter, info) => info.ParameterType.IsInstanceOfType(parameter.Value)).All(b => b) + select method); + + MethodInfo returnMethodInfo = null; + foreach (MethodInfo method in methods) + { + returnMethodInfo = method; + if (method.GetParameters().Zip(message.Parameters.OfType(), (info, parameter) => + parameter.Value.GetType().IsAssignableFrom(info.ParameterType) + ).All(b => b)) + { + break; + } + } + + return returnMethodInfo; +#else + var methods = (from method in t.GetMethods() + where method.Name == methodName + let methodParameters = method.GetParameters() + where message.Parameters.Count == methodParameters.Length + && message.Parameters.Zip(methodParameters, + (parameter, info) => info.ParameterType.IsInstanceOfType(parameter.Value)).All(b => b) + select method); + + MethodInfo returnMethodInfo = null; + foreach (MethodInfo method in methods) + { + returnMethodInfo = method; + if (method.GetParameters().Zip(message.Parameters, (info, parameter) => + parameter.Value.GetType().IsAssignableFrom(info.ParameterType) + ).All(b => b)) + { + break; + } + } + + return returnMethodInfo; #endif } } diff --git a/src/Caliburn.Micro.Platform/Platforms/Xamarin.Forms/ActionMessage.cs b/src/Caliburn.Micro.Platform/Platforms/Xamarin.Forms/ActionMessage.cs index 31013a232..dfb8c8794 100644 --- a/src/Caliburn.Micro.Platform/Platforms/Xamarin.Forms/ActionMessage.cs +++ b/src/Caliburn.Micro.Platform/Platforms/Xamarin.Forms/ActionMessage.cs @@ -313,31 +313,7 @@ public override string ToString() /// The matching method, if available. public static Func GetTargetMethod = (message, target) => { - //return (from method in target.GetType().GetRuntimeMethods() - // where method.Name == message.MethodName - // let methodParameters = method.GetParameters() - // where message.Parameters.Count == methodParameters.Length - // select method).FirstOrDefault(); - var methods = (from method in target.GetType().GetRuntimeMethods() - where method.Name == message.MethodName - let methodParameters = method.GetParameters() - where message.Parameters.Count == methodParameters.Length && message.Parameters.OfType().Zip(methodParameters, - (parameter, info) => info.ParameterType.IsInstanceOfType(parameter.Value)).All(b => b) - select method); - - MethodInfo returnMethodInfo = null; - foreach (MethodInfo method in methods) - { - returnMethodInfo = method; - if (method.GetParameters().Zip(message.Parameters.OfType(), (info, parameter) => - parameter.Value.GetType().IsAssignableFrom(info.ParameterType) - ).All(b => b)) - { - break; - } - } - - return returnMethodInfo; + return GetMethodInfo(target.GetType(), message.MethodName, message); }; /// @@ -463,7 +439,7 @@ static MethodInfo TryFindGuardMethod(ActionExecutionContext context, IEnumerable MethodInfo guard = null; foreach (string possibleGuardName in possibleGuardNames) { - guard = GetMethodInfo(targetType, possibleGuardName); + guard = GetMethodInfo(targetType, possibleGuardName, context.Message); if (guard != null) break; } @@ -515,5 +491,30 @@ static MethodInfo TryFindGuardMethod(ActionExecutionContext context, IEnumerable static MethodInfo GetMethodInfo(Type t, string methodName) { return t.GetRuntimeMethods().SingleOrDefault(m => m.Name == methodName); } + + static MethodInfo GetMethodInfo(Type t, string methodName, ActionMessage message) + { + var methods = (from method in t.GetRuntimeMethods() + where method.Name == methodName + let methodParameters = method.GetParameters() + where message.Parameters.Count == methodParameters.Length + && message.Parameters.OfType().Zip(methodParameters, + (parameter, info) => info.ParameterType.IsInstanceOfType(parameter.Value)).All(b => b) + select method); + + MethodInfo returnMethodInfo = null; + foreach (MethodInfo method in methods) + { + returnMethodInfo = method; + if (method.GetParameters().Zip(message.Parameters.OfType(), (info, parameter) => + parameter.Value.GetType().IsAssignableFrom(info.ParameterType) + ).All(b => b)) + { + break; + } + } + + return returnMethodInfo; + } } }