public void InvokeAction2 <A1, A2> (object d, A1 a1, A2 a2) { Stats.Increment(StatsCounter.InvokeBinderInvoked); TypeLogger.LogType(d); Action <A1, A2> a = d as Action <A1, A2>; if (a != null) { a(a1, a2); return; } Stats.Increment(StatsCounter.InvokeBinderInvoked_Slow); Delegate del = (Delegate)d; sArgs [0] = a1; sArgs [1] = a2; bool canConvert = MethodBinder.ConvertArguments(del.Method, null, sArgs, 2, ref mConvertedArgs); Debug.Assert(canConvert, "Could not convert parameters"); del.DynamicInvoke(mConvertedArgs); }
public TR InvokeFunc4 <A1, A2, A3, A4, TR> (object d, A1 a1, A2 a2, A3 a3, A4 a4) { Stats.Increment(StatsCounter.InvokeBinderInvoked); TypeLogger.LogType(d); Func <A1, A2, A3, A4, TR> f = d as Func <A1, A2, A3, A4, TR>; if (f != null) { Stats.Increment(StatsCounter.InvokeBinderInvoked_Fast); return(f(a1, a2, a3, a4)); } Stats.Increment(StatsCounter.InvokeBinderInvoked_Slow); Delegate del = (Delegate)d; sArgs [0] = a1; sArgs [1] = a2; sArgs [2] = a3; sArgs [3] = a4; bool canConvert = MethodBinder.ConvertArguments(del.Method, null, sArgs, 4, ref mConvertedArgs); Debug.Assert(canConvert, "Could not convert parameters"); return((TR)del.DynamicInvoke(mConvertedArgs)); }
public TR InvokeFunc9 <A1, A2, A3, A4, A5, A6, A7, A8, A9, TR> (object d, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { Stats.Increment(StatsCounter.InvokeBinderInvoked); TypeLogger.LogType(d); Func <A1, A2, A3, A4, A5, A6, A7, A8, A9, TR> f = d as Func <A1, A2, A3, A4, A5, A6, A7, A8, A9, TR>; if (f != null) { Stats.Increment(StatsCounter.InvokeBinderInvoked_Fast); return(f(a1, a2, a3, a4, a5, a6, a7, a8, a9)); } Stats.Increment(StatsCounter.InvokeBinderInvoked_Slow); Delegate del = (Delegate)d; sArgs [0] = a1; sArgs [1] = a2; sArgs [2] = a3; sArgs [3] = a4; sArgs [4] = a5; sArgs [5] = a6; sArgs [6] = a7; sArgs [7] = a8; sArgs [8] = a9; bool canConvert = MethodBinder.ConvertArguments(del.Method, null, sArgs, 9, ref mConvertedArgs); Debug.Assert(canConvert, "Could not convert parameters"); return((TR)del.DynamicInvoke(mConvertedArgs)); }
public void InvokeAction8 <A1, A2, A3, A4, A5, A6, A7, A8> (object d, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { Stats.Increment(StatsCounter.InvokeBinderInvoked); TypeLogger.LogType(d); Action <A1, A2, A3, A4, A5, A6, A7, A8> a = d as Action <A1, A2, A3, A4, A5, A6, A7, A8>; if (a != null) { Stats.Increment(StatsCounter.InvokeBinderInvoked_Fast); a(a1, a2, a3, a4, a5, a6, a7, a8); return; } Stats.Increment(StatsCounter.InvokeBinderInvoked_Slow); Delegate del = (Delegate)d; sArgs [0] = a1; sArgs [1] = a2; sArgs [2] = a3; sArgs [3] = a4; sArgs [4] = a5; sArgs [5] = a6; sArgs [6] = a7; sArgs [7] = a8; bool canConvert = MethodBinder.ConvertArguments(del.Method, null, sArgs, 8, ref mConvertedArgs); Debug.Assert(canConvert, "Could not convert parameters"); del.DynamicInvoke(mConvertedArgs); }
public T SetIndexAs <T> (object o, int index, T value) { Stats.Increment(StatsCounter.SetIndexBinderInvoked); Stats.Increment(StatsCounter.SetIndexBinder_Int_Invoked); TypeLogger.LogType(o); var l = o as IList <T>; if (l != null) { l [index] = value; return(value); } var l2 = o as IList; if (l2 != null) { l2 [index] = value; return(value); } var d = o as IDictionary <int, T>; if (d != null) { d[index] = value; return(value); } var d2 = o as IDictionary; if (d2 != null) { d2[index] = value; return(value); } return(default(T)); }
public TR InvokeFunc0 <TR> (object d) { Stats.Increment(StatsCounter.InvokeBinderInvoked); TypeLogger.LogType(d); Func <TR> f = d as Func <TR>; if (f != null) { Stats.Increment(StatsCounter.InvokeBinderInvoked_Fast); return(f()); } Stats.Increment(StatsCounter.InvokeBinderInvoked_Slow); Delegate del = (Delegate)d; bool canConvert = MethodBinder.ConvertArguments(del.Method, null, sArgs, 0, ref mConvertedArgs); Debug.Assert(canConvert, "Could not convert parameters"); return((TR)del.DynamicInvoke(mConvertedArgs)); }
public void InvokeAction0(object d) { Stats.Increment(StatsCounter.InvokeBinderInvoked); TypeLogger.LogType(d); Action a = d as Action; if (a != null) { Stats.Increment(StatsCounter.InvokeBinderInvoked_Fast); a(); return; } Stats.Increment(StatsCounter.InvokeBinderInvoked_Slow); Delegate del = (Delegate)d; bool canConvert = MethodBinder.ConvertArguments(del.Method, null, sArgs, 0, ref mConvertedArgs); Debug.Assert(canConvert, "Could not convert parameters"); del.DynamicInvoke(mConvertedArgs); }
/// <summary> /// Invokes the method on o (potentially using a previous invoker as a hint). /// /// Note that this method works if the parameters haven been boxed, return value is also boxed. /// </summary> /// <param name="invoker">The previous invoker as a hint, null if we could not get the invoker during the fast path.</param> /// <param name="o">The target of the invocation.</param> private object ResolveAndInvoke(object o, bool invokeOnly) { // Property and same target, or same type has already been checked earlier (by the fast path) // So here we have a new target type, we have an overloading, or this is the first time // Parameters have been boxed and stored in mArgs already. // Note that if we are overloading, we still do a full CreateDelegate work, even if we had the same type, target and method... // This is slow, however it should pretty much never happen in game code. if ((mInvoker == null) && (invokeOnly == false)) { // It means that we did not get the invoker from the fast path (overloaded - rare - or it is the first time - very common). var dc = o as IDynamicClass; if (dc != null) { object value; if (dc.__TryGetDynamicValue(mName, out value) && value is Delegate) { var func = value as Delegate; // Assume that most time, it is due to the first execution, so don't compare with previous version mInvoker = ActionCreator.CreateInvoker(func); // This is going to use an invoker factory (can be registered by user too for more optimal code). invokeOnly = true; } } } if (invokeOnly) { Stats.Increment(StatsCounter.InvokeMemberBinderInvoked_Slow); return(mInvoker.SafeInvokeWith(mArgs)); } // If we reached this point, we have to do a new resolve, then invoke // determine object type Type otype; bool isStatic; if (o is Type) { // this is a static method invocation where o is the class otype = (Type)o; isStatic = true; } else { // this is a instance method invocation otype = o.GetType(); isStatic = false; } // see if type has changed if (otype != mType) { // re-resolve method list if type has changed mType = otype; // get method list for type and method name BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public; if (isStatic) { flags |= BindingFlags.Static; } else { flags |= BindingFlags.Instance; } mMethodList = MethodBinder.LookupMethodList(mType, mName, flags, mArgs.Length); // select new method to use, this will try to reuse mInvoker = SelectMethod(o); } else if (mOverloadState == OverloadState.HasOverload) { // if there are overloads we select the method every time // we could look into a more optimal way of doing this if it becomes a problem mInvoker = SelectMethod(o); } else { // Same instance type, no overload, so should be the same method (or none). // We might be able to update the invoker if only the target changed mInvoker = InvokerBase.UpdateOrCreate(mInvoker, o, mMethod.Method); } Stats.Increment(StatsCounter.InvokeMemberBinderInvoked_Slow); TypeLogger.LogType(o); return(mInvoker.SafeInvokeWith(mArgs)); }
public T SetIndexAs <T> (object o, int index, T value) { Stats.Increment(StatsCounter.SetIndexBinderInvoked); Stats.Increment(StatsCounter.SetIndexBinder_Int_Invoked); TypeLogger.LogType(o); // get accessor for value type T var accessor = o as IDynamicAccessor <T>; if (accessor != null) { accessor.SetIndex(index, value); return(value); } // fallback on untyped accessor var untypedAccessor = o as IDynamicAccessorUntyped; if (untypedAccessor != null) { untypedAccessor.SetIndex(index, (object)value); return(value); } var l = o as IList <T>; if (l != null) { l [index] = value; return(value); } var l2 = o as IList; if (l2 != null) { int count = l2.Count; if (index < count) { l2 [index] = value; } else if (index == count) { l2.Add(value); } else { while (l2.Count < index) { l2.Add(default(T)); } l2 [index] = value; } return(value); } var d = o as IDictionary <int, T>; if (d != null) { d[index] = value; return(value); } var d2 = o as IDictionary; if (d2 != null) { d2[index] = value; return(value); } return(value); }
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)); }
/// <summary> /// This is the most generic method for getting a member's value. /// It will attempt to resolve the member by name and the get its value by invoking the /// callsite's delegate /// </summary> public T GetMember <T> (object o) { Stats.Increment(StatsCounter.GetMemberBinderInvoked); TypeLogger.LogType(o); // get accessor for value type T var accessor = o as IDynamicAccessor <T>; if (accessor != null) { return(accessor.GetMember(mName, ref mNameHint)); } // fallback on object accessor and cast it to T var untypedAccessor = o as IDynamicAccessorUntyped; if (untypedAccessor != null) { // value can be null, undefined, or of type T object value = untypedAccessor.GetMember(mName, ref mNameHint); // convert value to T if (value == null) { return(default(T)); } else if (value is T) { return((T)value); } else if (Dynamic.IsUndefined(value)) { return(Dynamic.GetUndefinedValue <T>()); } else { return(PlayScript.Dynamic.ConvertValue <T>(value)); } } // resolve as dictionary (this is usually an expando) var dict = o as IDictionary <string, object>; if (dict != null) { Stats.Increment(StatsCounter.GetMemberBinder_Expando); // special case this for expando objects object value; if (dict.TryGetValue(mName, out value)) { // fast path empty cast just in case if (value is T) { return((T)value); } else { return(PlayScript.Dynamic.ConvertValue <T>(value)); } } // key not found return(Dynamic.GetUndefinedValue <T>()); } if (PlayScript.Dynamic.IsNullOrUndefined(o)) { return(Dynamic.GetUndefinedValue <T>()); } // 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; } if (otype == mType) { // use cached resolve if (mProperty != null) { Func <T> func; if (o == mPreviousTarget) { func = (Func <T>)mPreviousFunc; } else { mPreviousFunc = func = ActionCreator.CreatePropertyGetAction <T>(o, mProperty); mPreviousTarget = o; } return(func()); } if (mField != null) { return(PlayScript.Dynamic.ConvertValue <T>(mField.GetValue(o))); } if (mMethod != null) { // construct method delegate return(PlayScript.Dynamic.ConvertValue <T>(Delegate.CreateDelegate(mTargetType, o, mMethod))); } // resolve as dynamic class var dc = o as IDynamicClass; if (dc != null) { object result = dc.__GetDynamicValue(mName); return(PlayScript.Dynamic.ConvertValue <T>(result)); } if (mName == "constructor") { return(PlayScript.Dynamic.ConvertValue <T> (otype)); } throw new System.InvalidOperationException("Unhandled member type in PSGetMemberBinder"); } // resolve name Stats.Increment(StatsCounter.GetMemberBinder_Resolve_Invoked); Stats.Start(StatsCounter.GetMemberBinder_Resolve_Time); // The constructor is a special synthetic property - we have to handle this for AS compatibility if (mName == "constructor") { // setup binding to field mType = otype; mPreviousFunc = null; mPreviousTarget = null; mProperty = null; mField = null; mMethod = null; mTargetType = typeof(Type); Stats.Stop(StatsCounter.GetMemberBinder_Resolve_Time); return(PlayScript.Dynamic.ConvertValue <T> (otype)); } // 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 getter = property.GetGetMethod(); if (getter != null && getter.IsStatic == isStatic) { // setup binding to property mType = otype; mPreviousFunc = null; mPreviousTarget = null; mProperty = property; mPropertyGetter = property.GetGetMethod(); mField = null; mMethod = null; mTargetType = property.PropertyType; Stats.Stop(StatsCounter.GetMemberBinder_Resolve_Time); return(PlayScript.Dynamic.ConvertValue <T>(mPropertyGetter.Invoke(o, null))); } } // 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; mPreviousFunc = null; mPreviousTarget = null; mProperty = null; mField = field; mMethod = null; mTargetType = field.FieldType; Stats.Stop(StatsCounter.GetMemberBinder_Resolve_Time); return(PlayScript.Dynamic.ConvertValue <T>(field.GetValue(o))); } } // resolve as method BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public; if (isStatic) { flags |= BindingFlags.Static; } else { flags |= BindingFlags.Instance; } var method = otype.GetMethod(mName, flags); if (method != null) { // setup binding to method mType = otype; mPreviousFunc = null; mPreviousTarget = null; mProperty = null; mField = null; mMethod = method; mTargetType = PlayScript.Dynamic.GetDelegateTypeForMethod(mMethod); Stats.Stop(StatsCounter.GetMemberBinder_Resolve_Time); return(PlayScript.Dynamic.ConvertValue <T>(Delegate.CreateDelegate(mTargetType, o, mMethod))); } if (o is IDynamicClass) { // dynamic class mType = otype; mPreviousFunc = null; mPreviousTarget = null; mProperty = null; mField = null; mMethod = null; object result = ((IDynamicClass)o).__GetDynamicValue(mName); Stats.Stop(StatsCounter.GetMemberBinder_Resolve_Time); return(PlayScript.Dynamic.ConvertValue <T>(result)); } Stats.Stop(StatsCounter.GetMemberBinder_Resolve_Time); return(Dynamic.GetUndefinedValue <T>()); }
/// <summary> /// This is the most generic method for getting a member's value. /// It will attempt to resolve the member by name and the get its value by invoking the /// callsite's delegate /// </summary> public T GetMember <T> (object o) { Stats.Increment(StatsCounter.GetMemberBinderInvoked); TypeLogger.LogType(o); // resolve as dictionary (this is usually an expando) var dict = o as IDictionary <string, object>; if (dict != null) { Stats.Increment(StatsCounter.GetMemberBinder_Expando); // special case this for expando objects object value; if (dict.TryGetValue(mName, out value)) { // fast path empty cast just in case if (value is T) { return((T)value); } else { return(PlayScript.Dynamic.ConvertValue <T>(value)); } } // key not found return(default(T)); } if (o == null) { return(default(T)); } // 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; } if (otype == mType) { // use cached resolve if (mProperty != null) { Func <T> func; if (o == mPreviousTarget) { func = (Func <T>)mPreviousFunc; } else { mPreviousFunc = func = ActionCreator.CreatePropertyGetAction <T>(o, mProperty); mPreviousTarget = o; } return(func()); } if (mField != null) { return(PlayScript.Dynamic.ConvertValue <T>(mField.GetValue(o))); } if (mMethod != null) { // construct method delegate return(PlayScript.Dynamic.ConvertValue <T>(Delegate.CreateDelegate(mTargetType, o, mMethod))); } // resolve as dynamic class var dc = o as IDynamicClass; if (dc != null) { object result = dc.__GetDynamicValue(mName); return(PlayScript.Dynamic.ConvertValue <T>(result)); } throw new System.InvalidOperationException("Unhandled member type in PSGetMemberBinder"); } // resolve name Stats.Increment(StatsCounter.GetMemberBinder_Resolve_Invoked); // resolve as property var property = otype.GetProperty(mName); if (property != null) { // found property var getter = property.GetGetMethod(); if (getter != null && getter.IsPublic && getter.IsStatic == isStatic) { // setup binding to property mType = otype; mPreviousFunc = null; mPreviousTarget = null; mProperty = property; mPropertyGetter = property.GetGetMethod(); mField = null; mMethod = null; mTargetType = property.PropertyType; return(PlayScript.Dynamic.ConvertValue <T>(mPropertyGetter.Invoke(o, null))); } } // resolve as field var field = otype.GetField(mName); if (field != null) { // found field if (field.IsPublic && field.IsStatic == isStatic) { // setup binding to field mType = otype; mPreviousFunc = null; mPreviousTarget = null; mProperty = null; mField = field; mMethod = null; mTargetType = field.FieldType; return(PlayScript.Dynamic.ConvertValue <T>(field.GetValue(o))); } } // resolve as method BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public; if (isStatic) { flags |= BindingFlags.Static; } else { flags |= BindingFlags.Instance; } var method = otype.GetMethod(mName, flags); if (method != null) { // setup binding to method mType = otype; mPreviousFunc = null; mPreviousTarget = null; mProperty = null; mField = null; mMethod = method; mTargetType = PlayScript.Dynamic.GetDelegateTypeForMethod(mMethod); // construct method delegate return(PlayScript.Dynamic.ConvertValue <T>(Delegate.CreateDelegate(mTargetType, o, mMethod))); } if (o is IDynamicClass) { // dynamic class mType = otype; mPreviousFunc = null; mPreviousTarget = null; mProperty = null; mField = null; mMethod = null; object result = ((IDynamicClass)o).__GetDynamicValue(mName); return(PlayScript.Dynamic.ConvertValue <T>(result)); } return(default(T)); }