【问题标题】:Why VS2010 IntelliSense fails when chaining methods with dynamic args为什么使用动态参数链接方法时 VS2010 IntelliSense 会失败
【发布时间】:2012-06-03 16:04:31
【问题描述】:

我想对 C# 4.0 动态方面的专家进行一些解释。

我有一个流利的构建器类来帮助在创建对象之前对其进行配置。这个接口有一个方法SetParameters(...):

    public FluentBuilder<TInterface> SetParameters(dynamic parameters)
    {
        _parameters = parameters;
        return this;
    }

我这样做是为了使用流畅的界面:

var order = new Order();

/* Setting up parameters */
dynamic parameters = new ExpandoObject();
parameters.Transaction = transactionObj;
parameters.CurrentPrincipal = Thread.CurrentPrincipal;

var proxiedOrder = ObjectProxyFactory
    .Configure<IOrder>(order)
    .FilterMethods(o => o.InsertOrder())
    .AddPreDecoration(AppConcerns.JoinSqlTransaction)
    .AddPreDecoration(AppConcerns.EnterLog)
    .AddPostDecoration(AppConcerns.ExitLog)
    .AddPostDecoration(AppConcerns.SecurityCheck)
    .SetParameters(parameters)
    .Teste() //this method doesn't exist in the fluent builder
    .CreateProxy();

var result = proxiedOrder.InsertOrder();

正如上面sn-p中所评论的,在流畅的接口中不存在名为Teste()的方法,但是intellisense允许在我调用SetParameters之后编写任何方法,就像它返回动态一样,但是正如你在代码中看到的那样,SetParameters返回非动态的 FluentInterface。

上面的代码在运行时编译成功会失败,因为在运行时在 FluentBuilder 类中找不到方法 Teste()。

为了在设计时解决这个问题,并获得正确的 Intelissense,我需要将参数转换为 ExpandoObject 类:

var proxiedOrder = ObjectProxyFactory
.Configure<IOrder>(order)
.FilterMethods(o => o.InsertOrder())
.AddPreDecoration(AppConcerns.JoinSqlTransaction)
.AddPreDecoration(AppConcerns.EnterLog)
.AddPostDecoration(AppConcerns.ExitLog)
.AddPostDecoration(AppConcerns.SecurityCheck)
.SetParameters((ExpandoObject)parameters) //cast to ExpandoObject
.Teste() //now intelissense is giving me an "red" error and solution will not compile
.CreateProxy();

var result = proxiedOrder.InsertOrder();

我发现,每当我在任何方法链接中传递 C# 动态参数时,在该方法接收到动态参数之后,对方法的后续调用将表现得像返回 C# 动态对象,即使返回类型方法它不是动态的。

这是一个错误吗?还是预期会发生这种情况?

【问题讨论】:

    标签: c# visual-studio-2010 c#-4.0


    【解决方案1】:

    预计会发生。任何涉及动态参数的方法调用都是动态解析的——直到执行时才能确定确切的重载,因此在编译时返回类型是未知的,因此它被视为dynamic。在某些情况下,C# 编译器可以推断出更多信息(例如,如果它是静态方法调用),但为简单起见,它不会。只有少数涉及动态值的表达式具有非动态类型。 (根据内存,is 运算符始终为bool,并且始终假定构造函数返回正在构造的类型。)

    编辑:我终于找到了规范参考。从第 7.6.5 节开始:

    如果以下至少一项成立,则调用表达式是动态绑定的(第 7.2.2 节):

    • 主表达式具有编译时类型动态。
    • 可选参数列表中的至少一个参数具有编译时类型动态,而主表达式没有委托类型。

    在这种情况下,编译器将调用表达式分类为动态类型的值。

    【讨论】:

    • 感谢您的澄清,现在我知道如果一个方法有一个动态参数,那么按照惯例,在使用方法链接时,结果将在设计时被认为是动态的。但我不同意这一点,因为调用的方法具有 IDE 可以在设计时推断的返回值。为什么动态参数会改变定义了返回类型的方法的结果?
    • 所以,是的,我们不确定你是否在链接 - 我们决定根本不给你智能感知 GL HF
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 1970-01-01
    • 2014-01-24
    • 2016-02-11
    • 1970-01-01
    相关资源
    最近更新 更多