【问题标题】:Why a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException if the invoked method is there?如果调用的方法存在,为什么会出现 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException?
【发布时间】:2023-03-31 17:20:01
【问题描述】:

我有以下代码创建一个分配给 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);
    }
}

为了测试它,我正在使用 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
    }

当我使用中间窗口询问我得到的 smtpClient 类型时:

smtpClient.GetType()
{<>f__AnonymousType0`1[System.Action`4[System.String,System.String,System.String,System.String]]}

当我询问它的成员时,我得到:

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}

所以,我的问题是:为什么我会遇到这个异常?

【问题讨论】:

  • uhmm...复制控制台应用程序中的所有代码(以及我的“主”方法中的测试方法的内容)它不会对我抛出任何异常。我猜您的 TestMethod 位于不同的 dll 中。也许您在 dll 或其引用中定位的 .NET 版本存在问题?
  • 这里也一样。当我运行您的代码(提供了帐户、资金等的合适定义)时,我没有例外。能否提供一个实际编译、运行、演示问题的小程序?
  • 你是对的,将测试代码复制到它工作的控制台应用程序的“Main()”方法中。现在,我可以看到问题:匿名类型(在测试 dll 中创建)在其 dll 中不可见。

标签: c# reflection dynamic anonymous-types


【解决方案1】:

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

[assembly: InternalsVisibleTo("NameSpace1.SubNameSpace1")]

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

【讨论】:

    【解决方案2】:

    匿名类型是内部的,如果您跨越程序集边界dynamic 无法解析该属性。

    尝试使用实际类型或 Expando 对象,而不是使用匿名类型。

    【讨论】:

    • 谢谢,理由是对的,具体的,能不能给点解决办法。
    • 将内部更改为对另一个程序集可见,这也是单元测试的一个很好的解决方案 - cstruter.com/blog/278
    • 请在 Visual Studio UserVoice 中投票支持此功能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 2020-06-09
    • 2015-12-07
    相关资源
    最近更新 更多