public override MetaObject BindGetMember(GetMemberBinder binder) { ContractUtils.RequiresNotNull(binder, "binder"); ExpandoClass klass = Value.Class; int index = klass.GetValueIndex(binder.Name, binder.IgnoreCase); string methodName = binder.IgnoreCase ? "ExpandoGetValueIgnoreCase" : "ExpandoGetValue"; Expression target; if (index == -1) { // the key does not exist, report a MissingMemberException target = Expression.Convert( Expression.Throw( Expression.New( typeof(MissingMemberException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(binder.Name) ) ), typeof(object) ); } else { target = Expression.Call( typeof(RuntimeOps).GetMethod(methodName), GetLimitedSelf(), Expression.Constant(klass), Expression.Constant(index) ); } // add the dynamic test for the target return(new MetaObject( AddDynamicTestAndDefer( binder, new MetaObject[] { this }, klass, null, target ), GetRestrictions() )); }
/// <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 ignoreCase, out ExpandoClass klass, out int index) { ExpandoClass originalClass = Value.Class; index = originalClass.GetValueIndex(name, ignoreCase); if (index == -1) { // go ahead and find a new class now... ExpandoClass newClass = originalClass.FindNewClass(name, ignoreCase); klass = newClass; index = newClass.GetValueIndex(name, ignoreCase); Debug.Assert(index != -1); return(originalClass); } else { klass = originalClass; return(null); } }