/// <summary> /// Gets the class and the index associated with the given name. Does not update the expando object. Instead /// this returns both the original and desired new class. A rule is created which includes the test for the /// original class, the promotion to the new class, and the set/delete based on the class post-promotion. /// </summary> private ExpandoClass GetClassEnsureIndex(string name, bool caseInsensitive, ExpandoObject obj, out ExpandoClass klass, out int index) { ExpandoClass originalClass = Value.Class; index = originalClass.GetValueIndex(name, caseInsensitive, obj); if (index == ExpandoObject.AmbiguousMatchFound) { klass = originalClass; return(null); } if (index == ExpandoObject.NoMatch) { // go ahead and find a new class now... ExpandoClass newClass = originalClass.FindNewClass(name); klass = newClass; index = newClass.GetValueIndexCaseSensitive(name); Debug.Assert(index != ExpandoObject.NoMatch); return(originalClass); } else { klass = originalClass; return(null); } }
private DynamicMetaObject BindGetOrInvokeMember(DynamicMetaObjectBinder binder, string name, bool ignoreCase, DynamicMetaObject fallback, Func <DynamicMetaObject, DynamicMetaObject> fallbackInvoke) { ExpandoClass klass = Value.Class; //try to find the member, including the deleted members int index = klass.GetValueIndex(name, ignoreCase, Value); ParameterExpression value = Expression.Parameter(typeof(object), "value"); Expression tryGetValue = Expression.Call( typeof(RuntimeOps).GetMethod("ExpandoTryGetValue"), GetLimitedSelf(), Expression.Constant(klass, typeof(object)), Expression.Constant(index), Expression.Constant(name), Expression.Constant(ignoreCase), value ); var result = new DynamicMetaObject(value, BindingRestrictions.Empty); if (fallbackInvoke != null) { result = fallbackInvoke(result); } result = new DynamicMetaObject( Expression.Block( new[] { value }, Expression.Condition( tryGetValue, result.Expression, fallback.Expression, typeof(object) ) ), result.Restrictions.Merge(fallback.Restrictions) ); return(AddDynamicTestAndDefer(binder, Value.Class, null, result)); }