我想对你的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()的方法在fluent界面中不存在,但是在我调用SetParameters之后,intelissense允许写任何方法,就像它返回动态一样,但正如你在代码中看到的那样,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#动态对象,即使返回类型为方法它不是动态的。
这是一个错误吗?或者预计这会发生吗?
答案 0 :(得分:6)
预计会发生。任何涉及动态参数的方法调用都是动态解析的 - 在执行时间之前无法确定确切的重载,因此返回类型在编译时是未知的,因此它被视为dynamic
。在某些情况下,C#编译器可能推断出更多信息(例如,如果它是静态方法调用),但为简单起见,它不会。只有涉及动态值的变量少数表达式具有非动态类型。 (从内存中,is
运算符始终为bool
,并且始终假定构造函数返回正在构造的类型。)
如果至少满足下列条件之一,则调用表达式是动态绑定的(第7.2.2节):
- primary-expression具有编译时类型dynamic。
- 可选参数列表的至少一个参数具有编译时类型动态,而primary-expression没有委托类型。
在这种情况下,编译器将invocation-expression分类为dynamic类型的值。