/// <summary>
 /// If instance == null -> then object reference will be got from object's userdata.
 /// Otherwise userdata ignored.
 /// </summary>
 public ScriptableObjectV8Handler(ScriptableObjectBinder binder, object instance, bool v8Extension)
 {
     this.instance      = instance;
     this.dispatchTable = binder.DispatchTable;
     this.v8Extension   = v8Extension;
 }
        private void Create()
        {
            var methods = GetMethods();
            var declaringMethodNames = new HashSet <string>(methods.Select(_ => _.Name));

            var dispatchTable         = new DispatchTable <MethodDef>(declaringMethodNames.Count);
            var propertyDispatchTable = new DispatchTable <PropertyDef>();

            foreach (var method in methods)
            {
                string declaringName         = method.Name;
                string scriptingName         = ConvertIdentifier(declaringName);
                string scriptingPropertyName = null;

                if (declaringName != scriptingName && declaringMethodNames.Contains(scriptingName))
                {
                    throw ExceptionBuilder.TypeAlreadyReservesMember(this.Type, scriptingName, declaringName);
                }

                var property = method.GetDeclaringTypeProperty();
                if (property != null)
                {
                    var declaringPropertyName = property.Name;
                    scriptingPropertyName = ConvertIdentifier(declaringPropertyName);

                    if (declaringPropertyName != scriptingPropertyName && declaringMethodNames.Contains(scriptingPropertyName))
                    {
                        throw ExceptionBuilder.TypeAlreadyReservesMember(this.Type, scriptingPropertyName, declaringPropertyName);
                    }
                }

                // method attributes
                var methodAttributes = method.IsStatic ? MethodDefAttributes.Static : MethodDefAttributes.None;

                if (property != null)
                {
                    methodAttributes |= MethodDefAttributes.Hidden;

                    if (method.IsGetterLikeSignature())
                    {
                        methodAttributes |= MethodDefAttributes.Getter;
                    }
                    else if (method.IsSetterLikeSignature())
                    {
                        methodAttributes |= MethodDefAttributes.Setter;
                    }
                }

                // put method info into a dispatch table
                // note: property accessors can't be overloaded
                var scriptableMethodInfo = dispatchTable.GetOrDefault(scriptingName);
                if (scriptableMethodInfo == null)
                {
                    scriptableMethodInfo = new MethodDef(scriptingName, methodAttributes);
                    dispatchTable.Add(scriptableMethodInfo);
                }
                scriptableMethodInfo.Add(method);

                // put property info into a property dispatch table
                if (property != null)
                {
                    var scriptablePropertyInfo = propertyDispatchTable.GetOrDefault(scriptingPropertyName);
                    if (scriptablePropertyInfo == null)
                    {
                        scriptablePropertyInfo = new PropertyDef(scriptingPropertyName);
                        propertyDispatchTable.Add(scriptablePropertyInfo);
                    }

                    scriptablePropertyInfo.Add(scriptableMethodInfo);
                }
            }

            dispatchTable.Optimize();
            propertyDispatchTable.Optimize();

            // TODO: prevent dispatch tables from modifying

            this.dispatchTable         = dispatchTable;
            this.propertyDispatchTable = propertyDispatchTable;
        }
 /// <summary>
 /// If instance == null -> then object reference will be got from object's userdata.
 /// Otherwise userdata ignored.
 /// </summary>
 public ScriptableObjectV8Accessor(ScriptableObjectBinder binder, object instance)
 {
     this.instance      = instance;
     this.dispatchTable = binder.PropertyDispatchTable;
 }