public void InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) { if (serviceHost.ImplementedContracts != null && serviceHost.ImplementedContracts.Count > 0) { EnsureThereAreApplicationEndpoints(description); } ValidateDescription(description, serviceHost); AspNetEnvironment.Current.AddHostingBehavior(serviceHost, description); ServiceBehaviorAttribute instanceSettings = description.Behaviors.Find<ServiceBehaviorAttribute>(); InitializeServicePerformanceCounters(serviceHost); Dictionary<ListenUriInfo, StuffPerListenUriInfo> stuffPerListenUriInfo = new Dictionary<ListenUriInfo, StuffPerListenUriInfo>(); Dictionary<EndpointAddress, Collection<EndpointInfo>> endpointInfosPerEndpointAddress = new Dictionary<EndpointAddress, Collection<EndpointInfo>>(); // Ensure ListenUri and group endpoints per ListenUri for (int i = 0; i < description.Endpoints.Count; i++) { //Ensure ReceiveContextSettings before building channel bool requiresReceiveContext = false; //at least one operation had ReceiveContextEnabledAttribute ServiceEndpoint endpoint = description.Endpoints[i]; foreach (OperationDescription operation in endpoint.Contract.Operations) { if (operation.Behaviors.Find<ReceiveContextEnabledAttribute>() != null) { requiresReceiveContext = true; break; } } if (requiresReceiveContext) { IReceiveContextSettings receiveContextSettings = endpoint.Binding.GetProperty<IReceiveContextSettings>(new BindingParameterCollection()); if (receiveContextSettings == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException( SR.GetString(SR.SFxReceiveContextSettingsPropertyMissing, endpoint.Contract.Name, typeof(ReceiveContextEnabledAttribute).Name, endpoint.Address.Uri.AbsoluteUri, typeof(IReceiveContextSettings).Name))); } //Enable ReceiveContext on the binding. receiveContextSettings.Enabled = true; } ListenUriInfo listenUriInfo = GetListenUriInfoForEndpoint(serviceHost, endpoint); if (!stuffPerListenUriInfo.ContainsKey(listenUriInfo)) { stuffPerListenUriInfo.Add(listenUriInfo, new StuffPerListenUriInfo()); } stuffPerListenUriInfo[listenUriInfo].Endpoints.Add(endpoint); } foreach (KeyValuePair<ListenUriInfo, StuffPerListenUriInfo> stuff in stuffPerListenUriInfo) { Uri listenUri = stuff.Key.ListenUri; ListenUriMode listenUriMode = stuff.Key.ListenUriMode; BindingParameterCollection parameters = stuff.Value.Parameters; Binding binding = stuff.Value.Endpoints[0].Binding; EndpointIdentity identity = stuff.Value.Endpoints[0].Address.Identity; // same EndpointAddressTable instance must be shared between channelDispatcher and parameters ThreadSafeMessageFilterTable<EndpointAddress> endpointAddressTable = new ThreadSafeMessageFilterTable<EndpointAddress>(); parameters.Add(endpointAddressTable); bool supportContextSession = false; // add service-level binding parameters foreach (IServiceBehavior behavior in description.Behaviors) { if (behavior is IContextSessionProvider) { supportContextSession = true; } behavior.AddBindingParameters(description, serviceHost, stuff.Value.Endpoints, parameters); } for (int i = 0; i < stuff.Value.Endpoints.Count; i++) { ServiceEndpoint endpoint = stuff.Value.Endpoints[i]; string viaString = listenUri.AbsoluteUri; // ensure all endpoints with this ListenUriInfo have same binding if (endpoint.Binding != binding) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ABindingInstanceHasAlreadyBeenAssociatedTo1, viaString))); } // ensure all endpoints with this ListenUriInfo have same identity if (!object.Equals(endpoint.Address.Identity, identity)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR.GetString(SR.SFxWhenMultipleEndpointsShareAListenUriTheyMustHaveSameIdentity, viaString))); } // add binding parameters (endpoint scope and below) AddMsmqIntegrationContractInformation(endpoint); SecurityContractInformationEndpointBehavior.ServerInstance.AddBindingParameters(endpoint, parameters); AddBindingParameters(endpoint, parameters); } // build IChannelListener and ChannelDispatcher IChannelListener listener; Type channelType = this.BuildChannelListener(stuff.Value, serviceHost, listenUri, listenUriMode, supportContextSession, out listener); XmlQualifiedName bindingQname = new XmlQualifiedName(binding.Name, binding.Namespace); ChannelDispatcher channelDispatcher = new ChannelDispatcher(listener, bindingQname.ToString(), binding); channelDispatcher.SetEndpointAddressTable(endpointAddressTable); stuff.Value.ChannelDispatcher = channelDispatcher; bool canReceiveInTransaction = false; // at least one operation is TransactionScopeRequired int transactedBatchSize = int.MaxValue; for (int i = 0; i < stuff.Value.Endpoints.Count; i++) { ServiceEndpoint endpoint = stuff.Value.Endpoints[i]; string viaString = listenUri.AbsoluteUri; EndpointFilterProvider provider = new EndpointFilterProvider(); EndpointDispatcher dispatcher = DispatcherBuilder.BuildDispatcher(serviceHost, description, endpoint, endpoint.Contract, provider); for (int j = 0; j < endpoint.Contract.Operations.Count; j++) { OperationDescription operation = endpoint.Contract.Operations[j]; OperationBehaviorAttribute operationBehavior = operation.Behaviors.Find<OperationBehaviorAttribute>(); if (null != operationBehavior && operationBehavior.TransactionScopeRequired) { canReceiveInTransaction = true; break; } } if (!endpointInfosPerEndpointAddress.ContainsKey(endpoint.Address)) { endpointInfosPerEndpointAddress.Add(endpoint.Address, new Collection<EndpointInfo>()); } endpointInfosPerEndpointAddress[endpoint.Address].Add(new EndpointInfo(endpoint, dispatcher, provider)); channelDispatcher.Endpoints.Add(dispatcher); TransactedBatchingBehavior batchBehavior = endpoint.Behaviors.Find<TransactedBatchingBehavior>(); if (batchBehavior == null) { transactedBatchSize = 0; } else { if (!canReceiveInTransaction) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MsmqBatchRequiresTransactionScope))); transactedBatchSize = System.Math.Min(transactedBatchSize, batchBehavior.MaxBatchSize); } if (PerformanceCounters.PerformanceCountersEnabled || PerformanceCounters.MinimalPerformanceCountersEnabled) { PerformanceCounters.AddPerformanceCountersForEndpoint(serviceHost, endpoint.Contract, dispatcher); } } // end foreach "endpoint" if (canReceiveInTransaction) { BindingElementCollection bindingElements = binding.CreateBindingElements(); foreach (BindingElement bindingElement in bindingElements) { ITransactedBindingElement txElement = bindingElement as ITransactedBindingElement; if (null != txElement && txElement.TransactedReceiveEnabled) { channelDispatcher.IsTransactedReceive = true; channelDispatcher.MaxTransactedBatchSize = transactedBatchSize; break; } } } //Set the mode of operation for ChannelDispatcher based on binding Settings. IReceiveContextSettings receiveContextSettings = binding.GetProperty<IReceiveContextSettings>(new BindingParameterCollection()); if (receiveContextSettings != null) { channelDispatcher.ReceiveContextEnabled = receiveContextSettings.Enabled; } serviceHost.ChannelDispatchers.Add(channelDispatcher); } // end foreach "ListenUri/ChannelDispatcher" group // run service behaviors for (int i = 0; i < description.Behaviors.Count; i++) { IServiceBehavior serviceBehavior = description.Behaviors[i]; serviceBehavior.ApplyDispatchBehavior(description, serviceHost); } foreach (KeyValuePair<ListenUriInfo, StuffPerListenUriInfo> stuff in stuffPerListenUriInfo) { for (int i = 0; i < stuff.Value.Endpoints.Count; i++) { ServiceEndpoint endpoint = stuff.Value.Endpoints[i]; // rediscover which dispatcher goes with this endpoint Collection<EndpointInfo> infos = endpointInfosPerEndpointAddress[endpoint.Address]; EndpointInfo info = null; foreach (EndpointInfo ei in infos) { if (ei.Endpoint == endpoint) { info = ei; break; } } EndpointDispatcher dispatcher = info.EndpointDispatcher; // run contract behaviors for (int k = 0; k < endpoint.Contract.Behaviors.Count; k++) { IContractBehavior behavior = endpoint.Contract.Behaviors[k]; behavior.ApplyDispatchBehavior(endpoint.Contract, endpoint, dispatcher.DispatchRuntime); } // run endpoint behaviors BindingInformationEndpointBehavior.Instance.ApplyDispatchBehavior(endpoint, dispatcher); TransactionContractInformationEndpointBehavior.Instance.ApplyDispatchBehavior(endpoint, dispatcher); for (int j = 0; j < endpoint.Behaviors.Count; j++) { IEndpointBehavior eb = endpoint.Behaviors[j]; eb.ApplyDispatchBehavior(endpoint, dispatcher); } // run operation behaviors DispatcherBuilder.BindOperations(endpoint.Contract, null, dispatcher.DispatchRuntime); } } this.EnsureRequiredRuntimeProperties(endpointInfosPerEndpointAddress); // Warn about obvious demux conflicts foreach (Collection<EndpointInfo> endpointInfos in endpointInfosPerEndpointAddress.Values) { // all elements of endpointInfos share the same Address (and thus EndpointListener.AddressFilter) if (endpointInfos.Count > 1) { for (int i = 0; i < endpointInfos.Count; i++) { for (int j = i + 1; j < endpointInfos.Count; j++) { // if not same ListenUri, won't conflict // if not same ChannelType, may not conflict (some transports demux based on this) // if they share a ChannelDispatcher, this means same ListenUri and same ChannelType if (endpointInfos[i].EndpointDispatcher.ChannelDispatcher == endpointInfos[j].EndpointDispatcher.ChannelDispatcher) { EndpointFilterProvider iProvider = endpointInfos[i].FilterProvider; EndpointFilterProvider jProvider = endpointInfos[j].FilterProvider; // if not default EndpointFilterProvider, we won't try to throw, you're on your own string commonAction; if (iProvider != null && jProvider != null && HaveCommonInitiatingActions(iProvider, jProvider, out commonAction)) { // you will definitely get a MultipleFiltersMatchedException at runtime, // so let's go ahead and throw now throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException( SR.GetString(SR.SFxDuplicateInitiatingActionAtSameVia, endpointInfos[i].Endpoint.ListenUri, commonAction))); } } } } } } }
public void InitializeServiceHost(System.ServiceModel.Description.ServiceDescription description, ServiceHostBase serviceHost) { if ((serviceHost.ImplementedContracts != null) && (serviceHost.ImplementedContracts.Count > 0)) { this.EnsureThereAreApplicationEndpoints(description); } this.ValidateDescription(description, serviceHost); AspNetEnvironment.Current.AddHostingBehavior(serviceHost, description); description.Behaviors.Find<ServiceBehaviorAttribute>(); this.InitializeServicePerformanceCounters(serviceHost); Dictionary<ListenUriInfo, StuffPerListenUriInfo> dictionary = new Dictionary<ListenUriInfo, StuffPerListenUriInfo>(); Dictionary<EndpointAddress, Collection<EndpointInfo>> endpointInfosPerEndpointAddress = new Dictionary<EndpointAddress, Collection<EndpointInfo>>(); for (int i = 0; i < description.Endpoints.Count; i++) { bool flag = false; ServiceEndpoint endpoint = description.Endpoints[i]; foreach (OperationDescription description2 in endpoint.Contract.Operations) { if (description2.Behaviors.Find<ReceiveContextEnabledAttribute>() != null) { flag = true; break; } } if (flag) { IReceiveContextSettings property = endpoint.Binding.GetProperty<IReceiveContextSettings>(new BindingParameterCollection()); if (property == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("SFxReceiveContextSettingsPropertyMissing", new object[] { endpoint.Contract.Name, typeof(ReceiveContextEnabledAttribute).Name, endpoint.Address.Uri.AbsoluteUri, typeof(IReceiveContextSettings).Name }))); } property.Enabled = true; } ListenUriInfo key = new ListenUriInfo(this.EnsureListenUri(serviceHost, endpoint), endpoint.ListenUriMode); if (!dictionary.ContainsKey(key)) { dictionary.Add(key, new StuffPerListenUriInfo()); } dictionary[key].Endpoints.Add(endpoint); } foreach (KeyValuePair<ListenUriInfo, StuffPerListenUriInfo> pair in dictionary) { ThreadSafeMessageFilterTable<EndpointAddress> table; IChannelListener listener; Uri listenUri = pair.Key.ListenUri; ListenUriMode listenUriMode = pair.Key.ListenUriMode; BindingParameterCollection bindingParameters = pair.Value.Parameters; Binding timeouts = pair.Value.Endpoints[0].Binding; EndpointIdentity objB = pair.Value.Endpoints[0].Address.Identity; table = new ThreadSafeMessageFilterTable<EndpointAddress> { table }; bool supportContextSession = false; foreach (IServiceBehavior behavior in description.Behaviors) { if (behavior is IContextSessionProvider) { supportContextSession = true; } behavior.AddBindingParameters(description, serviceHost, pair.Value.Endpoints, bindingParameters); } for (int k = 0; k < pair.Value.Endpoints.Count; k++) { ServiceEndpoint endpoint2 = pair.Value.Endpoints[k]; string absoluteUri = listenUri.AbsoluteUri; if (endpoint2.Binding != timeouts) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("ABindingInstanceHasAlreadyBeenAssociatedTo1", new object[] { absoluteUri }))); } if (!object.Equals(endpoint2.Address.Identity, objB)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("SFxWhenMultipleEndpointsShareAListenUriTheyMustHaveSameIdentity", new object[] { absoluteUri }))); } AddMsmqIntegrationContractInformation(endpoint2); SecurityContractInformationEndpointBehavior.ServerInstance.AddBindingParameters(endpoint2, bindingParameters); AddBindingParameters(endpoint2, bindingParameters); } this.BuildChannelListener(pair.Value, serviceHost, listenUri, listenUriMode, supportContextSession, out listener); XmlQualifiedName name = new XmlQualifiedName(timeouts.Name, timeouts.Namespace); ChannelDispatcher item = new ChannelDispatcher(listener, name.ToString(), timeouts); item.SetEndpointAddressTable(table); pair.Value.ChannelDispatcher = item; bool flag3 = false; int num3 = 0x7fffffff; for (int m = 0; m < pair.Value.Endpoints.Count; m++) { ServiceEndpoint endpoint3 = pair.Value.Endpoints[m]; string text1 = listenUri.AbsoluteUri; EndpointFilterProvider provider = new EndpointFilterProvider(new string[0]); EndpointDispatcher endpointDispatcher = BuildDispatcher(serviceHost, description, endpoint3, endpoint3.Contract, provider); for (int n = 0; n < endpoint3.Contract.Operations.Count; n++) { OperationDescription description3 = endpoint3.Contract.Operations[n]; OperationBehaviorAttribute attribute = description3.Behaviors.Find<OperationBehaviorAttribute>(); if ((attribute != null) && attribute.TransactionScopeRequired) { flag3 = true; break; } } if (!endpointInfosPerEndpointAddress.ContainsKey(endpoint3.Address)) { endpointInfosPerEndpointAddress.Add(endpoint3.Address, new Collection<EndpointInfo>()); } endpointInfosPerEndpointAddress[endpoint3.Address].Add(new EndpointInfo(endpoint3, endpointDispatcher, provider)); item.Endpoints.Add(endpointDispatcher); TransactedBatchingBehavior behavior2 = endpoint3.Behaviors.Find<TransactedBatchingBehavior>(); if (behavior2 == null) { num3 = 0; } else { if (!flag3) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("MsmqBatchRequiresTransactionScope"))); } num3 = Math.Min(num3, behavior2.MaxBatchSize); } if (PerformanceCounters.PerformanceCountersEnabled || PerformanceCounters.MinimalPerformanceCountersEnabled) { PerformanceCounters.AddPerformanceCountersForEndpoint(serviceHost, endpoint3.Contract, endpointDispatcher); } } if (flag3) { foreach (BindingElement element in timeouts.CreateBindingElements()) { ITransactedBindingElement element2 = element as ITransactedBindingElement; if ((element2 != null) && element2.TransactedReceiveEnabled) { item.IsTransactedReceive = true; item.MaxTransactedBatchSize = num3; break; } } } IReceiveContextSettings settings2 = timeouts.GetProperty<IReceiveContextSettings>(new BindingParameterCollection()); if (settings2 != null) { item.ReceiveContextEnabled = settings2.Enabled; } serviceHost.ChannelDispatchers.Add(item); } for (int j = 0; j < description.Behaviors.Count; j++) { description.Behaviors[j].ApplyDispatchBehavior(description, serviceHost); } foreach (KeyValuePair<ListenUriInfo, StuffPerListenUriInfo> pair2 in dictionary) { for (int num7 = 0; num7 < pair2.Value.Endpoints.Count; num7++) { ServiceEndpoint endpoint4 = pair2.Value.Endpoints[num7]; Collection<EndpointInfo> collection = endpointInfosPerEndpointAddress[endpoint4.Address]; EndpointInfo info2 = null; foreach (EndpointInfo info3 in collection) { if (info3.Endpoint == endpoint4) { info2 = info3; break; } } EndpointDispatcher dispatcher3 = info2.EndpointDispatcher; for (int num8 = 0; num8 < endpoint4.Contract.Behaviors.Count; num8++) { endpoint4.Contract.Behaviors[num8].ApplyDispatchBehavior(endpoint4.Contract, endpoint4, dispatcher3.DispatchRuntime); } BindingInformationEndpointBehavior.Instance.ApplyDispatchBehavior(endpoint4, dispatcher3); TransactionContractInformationEndpointBehavior.Instance.ApplyDispatchBehavior(endpoint4, dispatcher3); for (int num9 = 0; num9 < endpoint4.Behaviors.Count; num9++) { endpoint4.Behaviors[num9].ApplyDispatchBehavior(endpoint4, dispatcher3); } BindOperations(endpoint4.Contract, null, dispatcher3.DispatchRuntime); } } this.EnsureRequiredRuntimeProperties(endpointInfosPerEndpointAddress); foreach (Collection<EndpointInfo> collection2 in endpointInfosPerEndpointAddress.Values) { if (collection2.Count > 1) { for (int num10 = 0; num10 < collection2.Count; num10++) { for (int num11 = num10 + 1; num11 < collection2.Count; num11++) { if (collection2[num10].EndpointDispatcher.ChannelDispatcher == collection2[num11].EndpointDispatcher.ChannelDispatcher) { string str2; EndpointFilterProvider filterProvider = collection2[num10].FilterProvider; EndpointFilterProvider y = collection2[num11].FilterProvider; if (((filterProvider != null) && (y != null)) && HaveCommonInitiatingActions(filterProvider, y, out str2)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("SFxDuplicateInitiatingActionAtSameVia", new object[] { collection2[num10].Endpoint.ListenUri, str2 }))); } } } } } } }