| 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; } } } }