Binds to a method group using pretty standard .NET rules. The main difference from the JSBinder is that the number of arguments must be correct. Additionally, it is possible to bind to overloaded methods with the same number of arguments.
Inheritance: MethodBinder
示例#1
0
        /// <summary>
        /// Creates a new ClrStaticTypeWrapper object.
        /// </summary>
        /// <param name="engine"> The associated script engine. </param>
        /// <param name="type"> The CLR type to wrap. </param>
        /// <param name="flags"> <c>BindingFlags.Static</c> to populate static methods;
        /// <c>BindingFlags.Instance</c> to populate instance methods. </param>
        private ClrStaticTypeWrapper(ScriptEngine engine, Type type)
            : base(engine, GetPrototypeObject(engine, type))
        {
            this.WrappedType = type;

            // Pick up the public constructors, if any.
            var constructors = type.GetConstructors();
            if (constructors.Length > 0)
                this.constructBinder = new ClrBinder(constructors);
            else
            {
                // The built-in primitive types do not have constructors, but we still want to
                // allow their construction since there is no way to construct them otherwise.
                // Pretend that a constructor does exist.
                switch (Type.GetTypeCode(type))
                {
                    case TypeCode.Int32:
                        this.constructBinder = new ClrBinder(ReflectionHelpers.Convert_ToInt32_Double);
                        break;
                }
            }

            this.FastSetProperty("name", type.Name);
            if (this.constructBinder != null)
                this.FastSetProperty("length", this.constructBinder.FunctionLength);

            // Populate the fields, properties and methods.
            PopulateMembers(this, type, BindingFlags.Static);
        }
示例#2
0
        /// <summary>
        /// Generates a method that does type conversion and calls the bound method.
        /// </summary>
        /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
        /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
        /// <returns> A delegate that does type conversion and calls the method represented by this
        /// object. </returns>
        protected override void GenerateStub(ILGenerator generator, int argumentCount)
        {
            // Check for the correct number of arguments.
            if (argumentCount != 0)
            {
                EmitHelpers.EmitThrow(generator, ErrorType.TypeError, "Wrong number of arguments");
                EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
                generator.Complete();
                return;
            }

            if (this.field.IsStatic == false)
            {
                generator.LoadArgument(1);
                ClrBinder.EmitConversionToType(generator, this.field.DeclaringType, convertToAddress: true);
            }
            generator.LoadField(this.field);
            ClrBinder.EmitConversionToObject(generator, this.field.FieldType);
            generator.Complete();
        }
示例#3
0
 /// <summary>
 /// Generates a method that does type conversion and calls the bound method.
 /// </summary>
 /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
 /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
 /// <returns> A delegate that does type conversion and calls the method represented by this
 /// object. </returns>
 protected override void GenerateStub(ILGenerator generator, int argumentCount)
 {
     // Check for the correct number of arguments.
     if (argumentCount != 1)
     {
         EmitHelpers.EmitThrow(generator, "TypeError", "Wrong number of arguments");
         EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
         generator.Complete();
         return;
     }
     if (this.field.IsStatic == false)
     {
         generator.LoadArgument(1);
         ClrBinder.EmitConversionToType(generator, this.field.DeclaringType, convertToAddress: true);
     }
     generator.LoadArgument(2);
     generator.LoadInt32(0);
     generator.LoadArrayElement(typeof(object));
     ClrBinder.EmitConversionToType(generator, this.field.FieldType, convertToAddress: false);
     generator.StoreField(this.field);
     EmitHelpers.EmitUndefined(generator);
     generator.Complete();
 }
示例#4
0
        //     METHODS
        //_________________________________________________________________________________________


        /// <summary>
        /// Populates the given object with properties, field and methods based on the given .NET
        /// type.
        /// </summary>
        /// <param name="target"> The object to populate. </param>
        /// <param name="type"> The .NET type to search for methods. </param>
        /// <param name="flags"> <c>BindingFlags.Static</c> to populate static methods;
        /// <c>BindingFlags.Instance</c> to populate instance methods. </param>
        internal static void PopulateMembers(ObjectInstance target, Type type, BindingFlags flags)
        {
            // Register static methods as functions.
            var methodGroups = new Dictionary<string, List<MethodBase>>();
            foreach (var member in type.GetMembers(BindingFlags.Public | BindingFlags.DeclaredOnly | flags))
            {
                switch (member.MemberType)
                {
                    case MemberTypes.Method:
                        MethodInfo method = (MethodInfo)member;
                        List<MethodBase> methodGroup;
                        if (methodGroups.TryGetValue(method.Name, out methodGroup) == true)
                            methodGroup.Add(method);
                        else
                            methodGroups.Add(method.Name, new List<MethodBase>() { method });
                        break;

                    case MemberTypes.Property:
                        PropertyInfo property = (PropertyInfo)member;
                        var getMethod = property.GetGetMethod();
                        ClrFunction getter = getMethod == null ? null : new ClrFunction(target.Engine.Function.InstancePrototype, new ClrBinder(getMethod));
                        var setMethod = property.GetSetMethod();
                        ClrFunction setter = setMethod == null ? null : new ClrFunction(target.Engine.Function.InstancePrototype, new ClrBinder(setMethod));
                        target.DefineProperty(property.Name, new PropertyDescriptor(getter, setter, PropertyAttributes.NonEnumerable), false);

                        // Property getters and setters also show up as methods, so remove them here.
                        // NOTE: only works if properties are enumerated after methods.
                        if (getMethod != null)
                            methodGroups.Remove(getMethod.Name);
                        if (setMethod != null)
                            methodGroups.Remove(setMethod.Name);
                        break;
 
                    case MemberTypes.Field:
                        FieldInfo field = (FieldInfo)member;
                        ClrFunction fieldGetter = new ClrFunction(target.Engine.Function.InstancePrototype, new FieldGetterBinder(field));
                        ClrFunction fieldSetter = new ClrFunction(target.Engine.Function.InstancePrototype, new FieldSetterBinder(field));
                        target.DefineProperty(field.Name, new PropertyDescriptor(fieldGetter, fieldSetter, PropertyAttributes.NonEnumerable), false);
                        break;

                    case MemberTypes.Constructor:
                    case MemberTypes.NestedType:
                    case MemberTypes.Event:
                    case MemberTypes.TypeInfo:
                        // Support not yet implemented.
                        break;
                }
                
            }
            foreach (var methodGroup in methodGroups.Values)
            {
                var binder = new ClrBinder(methodGroup);
                var function = new ClrFunction(target.Engine.Function.InstancePrototype, binder);
                target.FastSetProperty(binder.Name, function, PropertyAttributes.NonEnumerable, overwriteAttributes: true);
            }
        }