Ran into an interesting runtime issue after some refactoring and have pinned in down to the following situation.
When passing a property from a dynamic object to a method on an Interface that has been inherited from a parent interface the runtime binder cannot find the method.
Here is a test to demonstrate both failure and success (when calling method directly on the parent interface type)
using System.Dynamic;
using Microsoft.CSharp.RuntimeBinder;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Test.Utility
{
public interface IEcho
{
string EchoString(string input);
}
public interface IInheritEcho : IEcho
{ }
public class EchoClass : IInheritEcho
{
public string EchoString(string input)
{
return input;
}
}
[TestClass]
public class RuntimeBinderTest
{
[TestMethod]
public void RuntimeBinder_should_work_when_dynamic_parameters_are_passed_to_method_from_inherited_interface()
{
//Arrange
dynamic dynObject = new ExpandoObject();
dynObject.Foo = "Bar";
IInheritEcho echomore = new EchoClass();
string echo = null;
string exceptionMessage = null;
//Act
try
{
echo = echomore.EchoString(dynObject.Foo);
}
catch (RuntimeBinderException e)
{
exceptionMessage = e.Message;
}
//Assert
Assert.AreEqual(echo, dynObject.Foo, false, exceptionMessage);
}
[TestMethod]
public void RuntimeBinder_should_work_when_dynamic_parameters_are_passed_to_method_from_noninherited_interface()
{
//Arrange
dynamic dynObject = new ExpandoObject();
dynObject.Foo = "Bar";
IEcho echomore = new EchoClass();
string echo = null;
string exceptionMessage = null;
//Act
try
{
echo = echomore.EchoString(dynObject.Foo);
}
catch (RuntimeBinderException e)
{
exceptionMessage = e.Message;
}
//Assert
Assert.AreEqual(echo, dynObject.Foo, false, exceptionMessage);
}
}
}
Test #1 Fails: Assert.AreEqual failed. Expected:<(null)>. Actual:. 'Test.Utility.IInheritEcho' does not contain a definition for 'EchoString'
Test #2 Succeeds.
My question is whether my assumption that the 1st test should pass is correct or is there a fundamental reason in the framework that it does not?
I know I can fix the issue by casting the parameters when I pass them in or assigning them to variables before passing them in. I'm more just curious as to the reason the inherited interface is causing the RuntimeBinder to fail...