File: FrameworkFork\System.ServiceModel\System\ServiceModel\InstanceContext.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.ServiceModel.Channels;
using System.ServiceModel.Diagnostics;
using System.ServiceModel.Dispatcher;
using System.Threading;
using System.Threading.Tasks;
 
namespace System.ServiceModel
{
    public sealed class InstanceContext : CommunicationObject, IExtensibleObject<InstanceContext>
    {
        private InstanceBehavior _behavior;
        private ConcurrencyInstanceContextFacet _concurrency;
        private ServiceChannelManager _channels;
        private ExtensionCollection<InstanceContext> _extensions;
        private object _serviceInstanceLock = new object();
        private SynchronizationContext _synchronizationContext;
        private object _userObject;
        private bool _wellKnown;
        private SynchronizedCollection<IChannel> _wmiChannels;
        private bool _isUserCreated;
 
        public InstanceContext(object implementation)
            : this(implementation, true)
        {
        }
 
        internal InstanceContext(object implementation, bool isUserCreated)
            : this(implementation, true, isUserCreated)
        {
        }
 
        internal InstanceContext(object implementation, bool wellKnown, bool isUserCreated)
        {
            if (implementation != null)
            {
                _userObject = implementation;
                _wellKnown = wellKnown;
            }
            _channels = new ServiceChannelManager(this);
            _isUserCreated = isUserCreated;
        }
 
        internal InstanceBehavior Behavior
        {
            get { return _behavior; }
            set
            {
                if (_behavior == null)
                {
                    _behavior = value;
                }
            }
        }
 
        internal ConcurrencyInstanceContextFacet Concurrency
        {
            get
            {
                if (_concurrency == null)
                {
                    lock (this.ThisLock)
                    {
                        if (_concurrency == null)
                            _concurrency = new ConcurrencyInstanceContextFacet();
                    }
                }
 
                return _concurrency;
            }
        }
 
        protected override TimeSpan DefaultCloseTimeout
        {
            get
            {
                return ServiceDefaults.CloseTimeout;
            }
        }
 
        protected override TimeSpan DefaultOpenTimeout
        {
            get
            {
                return ServiceDefaults.OpenTimeout;
            }
        }
 
        public IExtensionCollection<InstanceContext> Extensions
        {
            get
            {
                this.ThrowIfClosed();
                lock (this.ThisLock)
                {
                    if (_extensions == null)
                        _extensions = new ExtensionCollection<InstanceContext>(this, this.ThisLock);
                    return _extensions;
                }
            }
        }
 
        public ICollection<IChannel> IncomingChannels
        {
            get
            {
                this.ThrowIfClosed();
                return _channels.IncomingChannels;
            }
        }
 
        public ICollection<IChannel> OutgoingChannels
        {
            get
            {
                this.ThrowIfClosed();
                return _channels.OutgoingChannels;
            }
        }
 
        public SynchronizationContext SynchronizationContext
        {
            get { return _synchronizationContext; }
            set
            {
                this.ThrowIfClosedOrOpened();
                _synchronizationContext = value;
            }
        }
 
        new internal object ThisLock
        {
            get { return base.ThisLock; }
        }
 
        internal object UserObject
        {
            get { return _userObject; }
        }
 
        internal ICollection<IChannel> WmiChannels
        {
            get
            {
                if (_wmiChannels == null)
                {
                    lock (this.ThisLock)
                    {
                        if (_wmiChannels == null)
                        {
                            _wmiChannels = new SynchronizedCollection<IChannel>();
                        }
                    }
                }
                return _wmiChannels;
            }
        }
 
        protected override void OnAbort()
        {
            _channels.Abort();
        }
 
        internal void BindRpc(ref MessageRpc rpc)
        {
            this.ThrowIfClosed();
            _channels.IncrementActivityCount();
            rpc.SuccessfullyBoundInstance = true;
        }
 
        internal void FaultInternal()
        {
            this.Fault();
        }
 
        public object GetServiceInstance(Message message)
        {
            lock (_serviceInstanceLock)
            {
                this.ThrowIfClosedOrNotOpen();
 
                object current = _userObject;
 
                if (current != null)
                {
                    return current;
                }
 
                if (_behavior == null)
                {
                    Exception error = new InvalidOperationException(SRServiceModel.SFxInstanceNotInitialized);
                    if (message != null)
                    {
                        throw TraceUtility.ThrowHelperError(error, message);
                    }
                    else
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
                    }
                }
 
                object newUserObject;
                if (message != null)
                {
                    newUserObject = _behavior.GetInstance(this, message);
                }
                else
                {
                    newUserObject = _behavior.GetInstance(this);
                }
                if (newUserObject != null)
                {
                    SetUserObject(newUserObject);
                }
 
                return newUserObject;
            }
        }
 
 
        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new CloseAsyncResult(timeout, callback, state, this);
        }
 
        protected override void OnEndClose(IAsyncResult result)
        {
            CloseAsyncResult.End(result);
        }
 
        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new CompletedAsyncResult(callback, state);
        }
 
        protected override void OnEndOpen(IAsyncResult result)
        {
            CompletedAsyncResult.End(result);
        }
 
        protected override void OnClose(TimeSpan timeout)
        {
            _channels.Close(timeout);
        }
 
        protected override void OnOpen(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
        }
 
        protected override void OnOpened()
        {
            base.OnOpened();
        }
 
        protected override void OnOpening()
        {
            base.OnOpening();
        }
 
        protected internal override Task OnCloseAsync(TimeSpan timeout)
        {
            this.OnClose(timeout);
            return TaskHelpers.CompletedTask();
        }
 
        protected internal override Task OnOpenAsync(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            return TaskHelpers.CompletedTask();
        }
 
        private void SetUserObject(object newUserObject)
        {
            if (_behavior != null && !_wellKnown)
            {
                object oldUserObject = Interlocked.Exchange(ref _userObject, newUserObject);
            }
        }
 
        internal void UnbindRpc(ref MessageRpc rpc)
        {
            if (rpc.InstanceContext == this && rpc.SuccessfullyBoundInstance)
            {
                _channels.DecrementActivityCount();
            }
        }
 
        internal class CloseAsyncResult : AsyncResult
        {
            private InstanceContext _instanceContext;
            private TimeoutHelper _timeoutHelper;
 
            public CloseAsyncResult(TimeSpan timeout, AsyncCallback callback, object state, InstanceContext instanceContext)
                : base(callback, state)
            {
                _timeoutHelper = new TimeoutHelper(timeout);
                _instanceContext = instanceContext;
                IAsyncResult result = _instanceContext._channels.BeginClose(_timeoutHelper.RemainingTime(), PrepareAsyncCompletion(new AsyncCompletion(CloseChannelsCallback)), this);
                if (result.CompletedSynchronously && CloseChannelsCallback(result))
                {
                    base.Complete(true);
                }
            }
 
            public static void End(IAsyncResult result)
            {
                AsyncResult.End<CloseAsyncResult>(result);
            }
 
            private bool CloseChannelsCallback(IAsyncResult result)
            {
                Fx.Assert(object.ReferenceEquals(this, result.AsyncState), "AsyncState should be this");
                _instanceContext._channels.EndClose(result);
                return true;
            }
        }
    }
}