为什么Microsoft.CSharp.RuntimeBinder.RuntimeBinderException如果有调用的方法?

lon*_*ero 16 c# reflection dynamic anonymous-types

我有以下代码,它创建一个分配给smtpClient变量的动态对象.

public class TranferManager
{
    public void Tranfer(Account from, Account to, Money amount)
    {
        // Perform the required actions
        var smtpClient = New.SmtpClient();
        smtpClient.Send("info@bank.com", "from.Email", "Tranfer", "?");
        // In the previous line I get a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
        // with the description = "'object' does not contain a definition for 'Send'"
    }
}

public static class New
{
    public static dynamic SmtpClient(params object[] parameters)
    {
        return typeof(SmtpClient).New(parameters);
    }
}

public static class CreationExtensions
{
    private static Dictionary<Type, Func<object, dynamic>> builders =
        new Dictionary<Type, Func<object, dynamic>>();

    public static dynamic New(this Type type, params object[] parameters)
    {
        if(builders.ContainsKey(type))
            return builders[type](parameters);

        return Activator.CreateInstance(type, parameters);
    }

    public static void RegisterBuilder(this Type type, Func<object, dynamic> builder)
    {
        builders.Add(type, builder);
    }
}
Run Code Online (Sandbox Code Playgroud)

为了测试它我使用UT(下面):

    [TestMethod()]
    public void TranferTest()
    {
        typeof(SmtpClient).RegisterBuilder(p => 
            new
            {
                Send = new Action<string, string, string, string>(
                (from, to, subject, body) => { })
            }
        );

        var tm = new TranferManager();
        tm.Tranfer(new Account(), new Account(), new Money());
        // Assert
    }
Run Code Online (Sandbox Code Playgroud)

当我使用中间窗口时,请求我得到的smtpClient类型:

smtpClient.GetType()
{<>f__AnonymousType0`1[System.Action`4[System.String,System.String,System.String,System.String]]}
Run Code Online (Sandbox Code Playgroud)

当我要求其成员时,我得到:

smtpClient.GetType().GetMembers()
{System.Reflection.MemberInfo[7]}
    [0]: {System.Action`4[System.String,System.String,System.String,System.String] get_Send()}
    [1]: {System.String ToString()}
    [2]: {Boolean Equals(System.Object)}
    [3]: {Int32 GetHashCode()}
    [4]: {System.Type GetType()}
    [5]: {Void .ctor(System.Action`4[System.String,System.String,System.String,System.String])}
    [6]: {System.Action`4[System.String,System.String,System.String,System.String] Send}
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是:为什么我得到那个例外?

jbt*_*ule 33

匿名类型是内部的,如果跨组装边界dynamic无法解析属性.

不要使用匿名类型,请尝试使用实际类型或Expando对象.

  • 将内部更改为对另一个程序集可见它也是单元测试的一个很好的解决方案 - http://cstruter.com/blog/278 (2认同)

use*_*202 9

在AssemblyInfo.cs中尝试添加以下内容:

[assembly: InternalsVisibleTo("NameSpace1.SubNameSpace1")]
Run Code Online (Sandbox Code Playgroud)

其中NamsSpace1是您的项目名称,SubNameSpace是您的动态/匿名对象的名称空间