Пример #1
0
        public NativeConstructor(
            Type type,
            IGlobal global,
            JsObject PrototypePrototype,
            JsObject prototype)
            : base(global, prototype)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            if (type.IsGenericType && type.ContainsGenericParameters)
            {
                throw new InvalidOperationException("A native constructor can't be built against an open generic");
            }
            this.m_marshaller  = global.Marshaller;
            this.reflectedType = type;
            this.Name          = type.FullName;
            if (!type.IsAbstract)
            {
                this.m_constructors = type.GetConstructors();
            }
            this.DefineOwnProperty(JsFunction.PROTOTYPE, PrototypePrototype == null ? (JsInstance)this.Global.ObjectClass.New((JsFunction)this) : (JsInstance)this.Global.ObjectClass.New((JsFunction)this, PrototypePrototype), PropertyAttributes.ReadOnly | PropertyAttributes.DontEnum | PropertyAttributes.DontDelete);
            this.m_overloads = new NativeOverloadImpl <ConstructorInfo, ConstructorImpl>(this.m_marshaller, new NativeOverloadImpl <ConstructorInfo, ConstructorImpl> .GetMembersDelegate(this.GetMembers), new NativeOverloadImpl <ConstructorInfo, ConstructorImpl> .WrapMmemberDelegate(this.WrapMember));
            if (type.IsValueType)
            {
                this.m_overloads.DefineCustomOverload(new Type[0], new Type[0], (ConstructorImpl)Delegate.CreateDelegate(typeof(ConstructorImpl), typeof(NativeConstructor).GetMethod("CreateStruct", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(type)));
            }
            Dictionary <string, LinkedList <MethodInfo> > dictionary = new Dictionary <string, LinkedList <MethodInfo> >();

            foreach (MethodInfo method in type.GetMethods(BindingFlags.Static | BindingFlags.Public))
            {
                if (!method.ReturnType.IsByRef)
                {
                    if (!dictionary.ContainsKey(method.Name))
                    {
                        dictionary[method.Name] = new LinkedList <MethodInfo>();
                    }
                    dictionary[method.Name].AddLast(method);
                }
            }
            foreach (KeyValuePair <string, LinkedList <MethodInfo> > keyValuePair in dictionary)
            {
                this.DefineOwnProperty(keyValuePair.Key, (JsInstance)this.ReflectOverload((ICollection <MethodInfo>)keyValuePair.Value));
            }
            foreach (PropertyInfo property in type.GetProperties(BindingFlags.Static | BindingFlags.Public))
            {
                this.DefineOwnProperty((Descriptor)this.Global.Marshaller.MarshalPropertyInfo(property, (JsDictionaryObject)this));
            }
            foreach (FieldInfo field in type.GetFields(BindingFlags.Static | BindingFlags.Public))
            {
                this.DefineOwnProperty((Descriptor)this.Global.Marshaller.MarshalFieldInfo(field, (JsDictionaryObject)this));
            }
            if (type.IsEnum)
            {
                string[] names    = Enum.GetNames(type);
                object[] objArray = new object[names.Length];
                Enum.GetValues(type).CopyTo((Array)objArray, 0);
                for (int index = 0; index < names.Length; ++index)
                {
                    this.DefineOwnProperty(names[index], (JsInstance)this.Global.ObjectClass.New(objArray[index], this.PrototypeProperty));
                }
            }
            foreach (Type nestedType in type.GetNestedTypes(BindingFlags.Public))
            {
                this.DefineOwnProperty(nestedType.Name, this.Global.Marshaller.MarshalClrValue <Type>(nestedType), PropertyAttributes.DontEnum);
            }
            LinkedList <MethodInfo> linkedList1 = new LinkedList <MethodInfo>();
            LinkedList <MethodInfo> linkedList2 = new LinkedList <MethodInfo>();

            foreach (PropertyInfo property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                ParameterInfo[] indexParameters = property.GetIndexParameters();
                if (indexParameters == null || indexParameters.Length == 0)
                {
                    this.m_properties.AddLast(global.Marshaller.MarshalPropertyInfo(property, (JsDictionaryObject)this));
                }
                else if (property.Name == "Item" && indexParameters.Length == 1)
                {
                    if (property.CanRead)
                    {
                        linkedList1.AddLast(property.GetGetMethod());
                    }
                    if (property.CanWrite)
                    {
                        linkedList2.AddLast(property.GetSetMethod());
                    }
                }
            }
            if (linkedList1.Count > 0 || linkedList2.Count > 0)
            {
                MethodInfo[] methodInfoArray1 = new MethodInfo[linkedList1.Count];
                linkedList1.CopyTo(methodInfoArray1, 0);
                MethodInfo[] methodInfoArray2 = new MethodInfo[linkedList2.Count];
                linkedList2.CopyTo(methodInfoArray2, 0);
                this.m_indexer = (INativeIndexer) new NativeIndexer(this.m_marshaller, methodInfoArray1, methodInfoArray2);
            }
            if (this.reflectedType.IsArray)
            {
                this.m_indexer = (INativeIndexer)typeof(NativeArrayIndexer <>).MakeGenericType(this.reflectedType.GetElementType()).GetConstructor(new Type[1]
                {
                    typeof(Marshaller)
                }).Invoke(new object[1]
                {
                    (object)this.m_marshaller
                });
            }
            foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.Public))
            {
                this.m_properties.AddLast(global.Marshaller.MarshalFieldInfo(field, (JsDictionaryObject)this));
            }
        }
Пример #2
0
        public NativeConstructor(Type type, IGlobal global, JsObject PrototypePrototype, JsObject prototype) :
            base(global, prototype)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (type.IsGenericType && type.ContainsGenericParameters)
            {
                throw new InvalidOperationException("A native constructor can't be built against an open generic");
            }

            m_marshaller = global.Marshaller;

            reflectedType = type;
            Name          = type.FullName;

            if (!type.IsAbstract)
            {
                m_constructors = type.GetConstructors();
            }

            DefineOwnProperty(PROTOTYPE, PrototypePrototype == null ? Global.ObjectClass.New(this) : Global.ObjectClass.New(this, PrototypePrototype), PropertyAttributes.DontEnum | PropertyAttributes.DontDelete | PropertyAttributes.ReadOnly);

            m_overloads = new NativeOverloadImpl <ConstructorInfo, ConstructorImpl>(
                m_marshaller,
                new NativeOverloadImpl <ConstructorInfo, ConstructorImpl> .GetMembersDelegate(this.GetMembers),
                new NativeOverloadImpl <ConstructorInfo, ConstructorImpl> .WrapMmemberDelegate(this.WrapMember)
                );

            // if this is a value type, define a default constructor
            if (type.IsValueType)
            {
                m_overloads.DefineCustomOverload(
                    new Type[0],
                    new Type[0],
                    (ConstructorImpl)Delegate.CreateDelegate(
                        typeof(ConstructorImpl),
                        typeof(NativeConstructor).GetMethod("CreateStruct", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(type)
                        )
                    );
            }

            // now we should find all static members and add them as a properties

            // members are grouped by their names
            Dictionary <string, LinkedList <MethodInfo> > members = new Dictionary <string, LinkedList <MethodInfo> >();

            foreach (var info in type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public))
            {
                if (info.ReturnType.IsByRef)
                {
                    continue;
                }
                if (!members.ContainsKey(info.Name))
                {
                    members[info.Name] = new LinkedList <MethodInfo>();
                }

                members[info.Name].AddLast(info);
            }

            // add the members to the object
            foreach (var pair in members)
            {
                DefineOwnProperty(pair.Key, ReflectOverload(pair.Value));
            }

            // find and add all static properties and fields
            foreach (var info in type.GetProperties(BindingFlags.Static | BindingFlags.Public))
            {
                DefineOwnProperty(info.Name, Global.Marshaller.MarshalPropertyInfo(info, this));
            }

            foreach (var info in type.GetFields(BindingFlags.Static | BindingFlags.Public))
            {
                DefineOwnProperty(info.Name, Global.Marshaller.MarshalFieldInfo(info, this));
            }

            if (type.IsEnum)
            {
                string[] names  = Enum.GetNames(type);
                object[] values = new object[names.Length];
                Enum.GetValues(type).CopyTo(values, 0);

                for (int i = 0; i < names.Length; i++)
                {
                    DefineOwnProperty(names[i], Global.ObjectClass.New(values[i], PrototypeProperty));
                }
            }

            // find all nested types
            foreach (var info in type.GetNestedTypes(BindingFlags.Public))
            {
                DefineOwnProperty(info.Name, Global.Marshaller.MarshalClrValue(info), PropertyAttributes.DontEnum);
            }

            // find all instance properties and fields
            LinkedList <MethodInfo> getMethods = new LinkedList <MethodInfo>();
            LinkedList <MethodInfo> setMethods = new LinkedList <MethodInfo>();

            foreach (var info in type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public))
            {
                ParameterInfo[] indexerParams = info.GetIndexParameters();
                if (indexerParams == null || indexerParams.Length == 0)
                {
                    m_properties.AddLast(global.Marshaller.MarshalPropertyInfo(info, this));
                }
                else if (info.Name == "Item" && indexerParams.Length == 1)
                {
                    if (info.CanRead)
                    {
                        getMethods.AddLast(info.GetGetMethod());
                    }
                    if (info.CanWrite)
                    {
                        setMethods.AddLast(info.GetSetMethod());
                    }
                }
            }

            if (getMethods.Count > 0 || setMethods.Count > 0)
            {
                MethodInfo[] getters = new MethodInfo[getMethods.Count];
                getMethods.CopyTo(getters, 0);
                MethodInfo[] setters = new MethodInfo[setMethods.Count];
                setMethods.CopyTo(setters, 0);

                m_indexer = new NativeIndexer(m_marshaller, getters, setters);
            }

            if (reflectedType.IsArray)
            {
                m_indexer = (INativeIndexer)typeof(NativeArrayIndexer <>)
                            .MakeGenericType(reflectedType.GetElementType())
                            .GetConstructor(new Type[] { typeof(Marshaller) })
                            .Invoke(new object[] { m_marshaller });
            }

            foreach (var info in type.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public))
            {
                m_properties.AddLast(global.Marshaller.MarshalFieldInfo(info, this));
            }
        }