/// <summary>
/// Adds a dynamic test which checks if the version has changed. The test is only necessary for
/// performance as the methods will do the correct thing if called with an incorrect version.
/// </summary>
private DynamicMetaObject AddDynamicTestAndDefer(DynamicMetaObjectBinder binder, ExpandoClass klass, ExpandoClass originalClass, DynamicMetaObject succeeds)
{
Expression ifTestSucceeds = succeeds.Expression;
if (originalClass != null)
{
// we are accessing a member which has not yet been defined on this class.
// We force a class promotion after the type check. If the class changes the
// promotion will fail and the set/delete will do a full lookup using the new
// class to discover the name.
Debug.Assert(originalClass != klass);
ifTestSucceeds = Expression.Block(
Expression.Call(
null,
typeof(RuntimeOps).GetMethod("ExpandoPromoteClass"),
GetLimitedSelf(),
Expression.Constant(originalClass, typeof(object)),
Expression.Constant(klass, typeof(object))
),
succeeds.Expression
);
}
return(new DynamicMetaObject(
Expression.Condition(
Expression.Call(
null,
typeof(RuntimeOps).GetMethod("ExpandoCheckVersion"),
GetLimitedSelf(),
Expression.Constant(originalClass ?? klass, typeof(object))
),
ifTestSucceeds,
binder.GetUpdateExpression(ifTestSucceeds.Type)
),
GetRestrictions().Merge(succeeds.Restrictions)
));
}