protected virtual void unbind()
        {
            var context = this.context;

            if (_channels.ContainsKey(ns))
            {
                _channels.Remove(ns);
            }
            if (id == null)
            {
                return;
            }
            id = null;
            _instances.Clear();
            if (isFactory)
            {
                _principal.nativeObject.setNKScriptChannel(null);
            }
            _principal = null;
            context.NKremoveScriptMessageHandlerForName(id);
            _context   = null;
            _typeInfo  = null;
            _queue     = null;
            _instances = null;
            context    = null;
        }
        // Public methods
        public virtual async Task <NKScriptValue> bindPlugin <T>(T obj, string ns) where T : class
        {
            var context = this.context;

            context.setNKScriptChannel(this);
            if ((this.id != null) || (context == null))
            {
                return(null);
            }

            this.id = (NKScriptChannel.sequenceNumber++).ToString();

            context.NKaddScriptMessageHandler(this, id);

            string name;

            if (typeof(T) == typeof(Type))
            {
                // Class, not instance, passed to bindPlugin -- to be used in Factory constructor/instance pattern in js
                isFactory = true;
                _typeInfo = new NKScriptTypeInfo <T>(obj);
                name      = (obj as Type).Name;
                // Need to store the channel on the class itself so it can be found when native construct requests come in from other plugins
                obj.setNKScriptChannel(this);
            }
            else
            {
                name = (typeof(T)).Name;
                // Instance of Princpal passed to bindPlugin -- to be used in singleton/static pattern in js
                isFactory = false;
                _typeInfo = new NKScriptTypeInfo <T>(obj);
            }

            _principal         = new NKScriptValueNative(ns, this, 0, obj);
            this._instances[0] = _principal;
            _channels[ns]      = this;
            obj.setNKScriptValue(_principal);

            var export = new NKScriptExportProxy <T>(obj);

            var script = new NKScriptSource(_generateStubs(export, name), ns + "/plugin/" + name + ".js");
            await context.NKinjectScript(script);

            await export.initializeForContext(context);

            return(_principal);
        }