为什么在使用动态参数链接方法时VS2010 IntelliSense失败 [英] Why VS2010 IntelliSense fails when chaining methods with dynamic args
问题描述
我想向您解释C#4.0动态专家。
I would like some explanation of you experts in C# 4.0 dynamic.
我有一个熟练的生成器类,可以帮助在创建对象之前对其进行配置。该接口具有方法SetParameters(...):
I have a fluent builder class to help configure an object before creating it. This interface has a method SetParameters(...):
public FluentBuilder<TInterface> SetParameters(dynamic parameters)
{
_parameters = parameters;
return this;
}
我这样做是为了消耗流畅的界面:
I'm doing this to consume the fluent interface:
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。
As commented in the above snippet, the method called Teste() doesn't exists in the fluent interface, but intelissense allow write anymethod after I call SetParameters like it returning dynamic, but as you see in code, SetParameters returns FluentInterface that is not dynamic.
上面的代码已成功编译在运行时by将失败,因为在运行时将在FluentBuilder类中找不到Teste()方法。
The code above compiles sucessfully by in runtime will fail because in runtime the method Teste() will not be found in FluentBuilder class.
在设计时解决此问题并获得正确的Intelissense ,我需要将参数转换为ExpandoObject类:
To resolve this problem in design-time, and to get correct Intelissense, I need to cast the parameter to the ExpandoObject class:
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#动态对象,即使该方法的返回类型不是动态的。
I've found that, anytime I pass a C# dynamic parameter in any method chaining, after that method receiving the dynamic parameter, the subsequent calls to methods will behave like returning a C# dynamic object, even if the return type of the method it's not dynamic.
这是一个错误?还是会发生这种情况?
Is it a bug ? Or is this expected to happens ?
推荐答案
会发生这种情况。任何涉及动态参数的方法调用都是动态解决的-确切的重载直到执行时才能确定,因此返回类型在编译时是未知的,因此将其视为 dynamic
。在某些情况下,C#编译器可以推断出更多信息(例如,如果是静态方法调用),但为简单起见,它不能。只有很少一些涉及动态值的表达式具有非动态类型。 (从内存中, is
运算符始终为 bool
,并且始终假定构造函数返回正在构造的类型。 )
It's expected to happen. Any method call involving a dynamic argument is resolved dynamically - the exact overload can't be determined until execution time, so the return type is unknown at compile time, so it's treated as being dynamic
. In some cases the C# compiler could infer more information (e.g. if it's a static method call) but for simplicity it doesn't. Only a variable few expressions involving dynamic values have non-dynamic types. (From memory, the is
operator is always bool
, and a constructor is always assumed to return the type being constructed.)
编辑:我终于找到了规范参考。从第7.6.5节开始:
I've finally found the spec reference. From section 7.6.5:
如果至少有以下一项成立,则动态绑定调用表达式(第7.2.2节):
An invocation-expression is dynamically bound (§7.2.2) if at least one of the following holds:
- 主表达式的编译时类型为动态。
- 可选参数列表的至少一个参数具有编译时
在这种情况下,编译器将invocation-expression分类为dynamic类型的值。
In this case the compiler classifies the invocation-expression as a value of type dynamic.
这篇关于为什么在使用动态参数链接方法时VS2010 IntelliSense失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!