为什么VS2010智能感知在使用动态参数链接方法时失败

本文关键字:链接 参数 方法 失败 动态 智能 VS2010 感知 为什么 | 更新日期: 2023-09-27 18:36:05

我想对你们这些 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();

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

上面的代码在运行时成功

编译将失败,因为在运行时中,方法Teste()在FluentBuilder类中找不到。

为了在设计时解决此问题,并获得正确的智能感知,我需要将参数强制转换为 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# 动态对象,即使该方法的返回类型不是动态的。

这是一个错误吗?还是预计会发生?

为什么VS2010智能感知在使用动态参数链接方法时失败

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

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

如果至少存在

以下条件之一,则调用表达式将动态绑定 (§7.2.2):

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

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