Esempio n. 1
0
        /// <summary>
        /// This is the most generic method for setting a member's value.
        /// It will attempt to resolve the member by name and the set its value by invoking the
        /// callsite's delegate
        /// </summary>
        private static void SetMember <T> (CallSite site, object o, T value)
        {
#if BINDERS_RUNTIME_STATS
            Stats.Increment(StatsCounter.SetMemberBinderInvoked);
#endif

            var binder = (PSSetMemberBinder)site.Binder;

            // resolve as dictionary
            var dict = o as IDictionary;
            if (dict != null)
            {
                // special case this since it happens so much in object initialization
                dict[binder.name] = value;
                return;
            }

            // determine if this is a instance member or a static member
            bool isStatic;
            Type otype;

            if (o is System.Type)
            {
                // static member
                otype    = (System.Type)o;
                o        = null;
                isStatic = true;
            }
            else
            {
                // instance member

                otype    = o.GetType();
                isStatic = false;
            }

            // see if binding type is the same
            if (otype == binder.type)
            {
                // use cached resolve
                if (binder.property != null)
                {
                    Action <T> action;
                    if (o == binder.previousTarget)
                    {
                        action = (Action <T>)binder.previousAction;
                    }
                    else
                    {
                        binder.previousAction = action = ActionCreator.CreatePropertySetAction <T>(o, binder.property);
                        binder.previousTarget = o;
                    }
                    action(value);
                    return;
                }

                if (binder.field != null)
                {
                    object newValue = PlayScript.Dynamic.ConvertValue(value, binder.field.FieldType);
                    binder.field.SetValue(o, newValue);
                    return;
                }

                // resolve as dynamic class
                var dc = o as IDynamicClass;
                if (dc != null)
                {
                    dc.__SetDynamicValue(binder.name, value);
                    return;
                }

                throw new System.InvalidOperationException("Unhandled member type in PSSetMemberBinder");
            }

            // resolve name

#if BINDERS_RUNTIME_STATS
            Stats.Increment(StatsCounter.SetMemberBinder_Resolve_Invoked);
#endif

            otype    = o.GetType();
            isStatic = false;

            // resolve as property
            var property = otype.GetProperty(binder.name);
            if (property != null)
            {
                // found property
                var setter = property.GetSetMethod();
                if (setter != null && setter.IsPublic && setter.IsStatic == isStatic)
                {
                    // setup binding to property
                    binder.type     = otype;
                    binder.property = property;
                    binder.field    = null;
                    object newValue = PlayScript.Dynamic.ConvertValue(value, binder.property.PropertyType);
                    binder.property.SetValue(o, newValue, null);
                    return;
                }
            }

            // resolve as field
            var field = otype.GetField(binder.name);
            if (field != null)
            {
                // found field
                if (field.IsPublic && field.IsStatic == isStatic)
                {
                    // setup binding to field
                    binder.type     = otype;
                    binder.property = null;
                    binder.field    = field;
                    object newValue = PlayScript.Dynamic.ConvertValue(value, binder.field.FieldType);
                    binder.field.SetValue(o, newValue);
                    return;
                }
            }

            if (o is IDynamicClass)
            {
                // dynamic class
                binder.type     = otype;
                binder.property = null;
                binder.field    = null;
                ((IDynamicClass)o).__SetDynamicValue(binder.name, value);
                return;
            }

            // could not resolve name as property or field, and is not dynamic class or dictionary
            // invoke callback
            if (Binder.OnSetMemberError != null)
            {
                Binder.OnSetMemberError(o, binder.name, value);
            }
        }
Esempio n. 2
0
        public T SetMember <T>(object o, T value, bool valueTypeIsConstant = false)
        {
            Stats.Increment(StatsCounter.SetMemberBinderInvoked);

            TypeLogger.LogType(o);

            // get accessor for value type T
            var accessor = o as IDynamicAccessor <T>;

            if (accessor != null)
            {
                accessor.SetMember(mName, ref mNameHint, value);
                return(value);
            }

            // fallback on untyped accessor
            var untypedAccessor = o as IDynamicAccessorUntyped;

            if (untypedAccessor != null)
            {
                untypedAccessor.SetMember(mName, ref mNameHint, (object)value);
                return(value);
            }

            // resolve as dictionary
            var dict = o as IDictionary;

            if (dict != null)
            {
                // special case this since it happens so much in object initialization
                dict[mName] = value;
                return(value);
            }

            // determine if this is a instance member or a static member
            bool isStatic;
            Type otype;

            if (o is System.Type)
            {
                // static member
                otype    = (System.Type)o;
                o        = null;
                isStatic = true;
            }
            else
            {
                // instance member
                otype    = o.GetType();
                isStatic = false;
            }

            // see if binding type is the same
            if (otype == mType)
            {
                // use cached resolve
                if (mProperty != null)
                {
                    Action <T> action;
                    if (o == mPreviousTarget)
                    {
                        action = (Action <T>)mPreviousAction;
                    }
                    else
                    {
                        mPreviousAction = action = ActionCreator.CreatePropertySetAction <T>(o, mProperty);
                        mPreviousTarget = o;
                    }
                    action(value);
                    return(value);
                }

                // use cached resolve
                if (mProperty != null)
                {
                    mArgs[0] = value;
                    mPropertySetter.Invoke(o, BindingFlags.SuppressChangeType, null, mArgs, null);
                    return(value);
                }

                if (mField != null)
                {
                    mField.SetValue(o, value);
                    return(value);
                }

                // resolve as dynamic class
                var dc = o as IDynamicClass;
                if (dc != null)
                {
                    dc.__SetDynamicValue(mName, value);
                    return(value);
                }

                throw new System.InvalidOperationException("Unhandled member type in PSSetMemberBinder");
            }

            // resolve name
            Stats.Increment(StatsCounter.SetMemberBinder_Resolve_Invoked);
            Stats.Start(StatsCounter.SetMemberBinder_Resolve_Time);

            // resolve as property
            // TODO: we allow access to non-public properties for simplicity,
            // should cleanup to check access levels
            var property = otype.GetProperty(mName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

            if (property != null)
            {
                // found property
                var setter = property.GetSetMethod();
                if (setter != null && setter.IsStatic == isStatic)
                {
                    // setup binding to property
                    mType           = otype;
                    mProperty       = property;
                    mPropertySetter = property.GetSetMethod();
                    mField          = null;
                    mPreviousAction = null;
                    mPreviousTarget = null;

                    mArgs[0] = PlayScript.Dynamic.ConvertValue(value, property.PropertyType);
                    mPropertySetter.Invoke(o, mArgs);
                    Stats.Stop(StatsCounter.SetMemberBinder_Resolve_Time);
                    return(value);
                }
            }

            // resolve as field
            // TODO: we allow access to non-public fields for simplicity,
            // should cleanup to check access levels
            var field = otype.GetField(mName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

            if (field != null)
            {
                // found field
                if (field.IsStatic == isStatic)
                {
                    // setup binding to field
                    mType           = otype;
                    mProperty       = null;
                    mField          = field;
                    mPreviousAction = null;
                    mPreviousTarget = null;

                    // resolve conversion function
                    object newValue = PlayScript.Dynamic.ConvertValue(value, mField.FieldType);
                    mField.SetValue(o, newValue);
                    Stats.Stop(StatsCounter.SetMemberBinder_Resolve_Time);
                    return(value);
                }
            }

            if (o is IDynamicClass)
            {
                // dynamic class
                mType           = otype;
                mProperty       = null;
                mField          = null;
                mPreviousAction = null;
                mPreviousTarget = null;
                ((IDynamicClass)o).__SetDynamicValue(mName, value);
                Stats.Stop(StatsCounter.SetMemberBinder_Resolve_Time);
                return(value);
            }

            Stats.Stop(StatsCounter.SetMemberBinder_Resolve_Time);

            // failed
            return(default(T));
        }