internal static void InitializeServiceHost(ServiceHostBase serviceHost, IServiceProvider services) { ServiceDescription description = serviceHost.Description; if (serviceHost.ImplementedContracts != null && serviceHost.ImplementedContracts.Count > 0) { EnsureThereAreApplicationEndpoints(description); } ValidateDescription(serviceHost); var stuffPerListenUriInfo = new Dictionary <ListenUriInfo, StuffPerListenUriInfo>(); var endpointInfosPerEndpointAddress = new Dictionary <EndpointAddress, Collection <EndpointInfo> >(); // Ensure ListenUri and group endpoints per ListenUri for (int i = 0; i < description.Endpoints.Count; i++) { ServiceEndpoint endpoint = description.Endpoints[i]; ListenUriInfo listenUriInfo = GetListenUriInfoForEndpoint(serviceHost, endpoint); if (!stuffPerListenUriInfo.ContainsKey(listenUriInfo)) { stuffPerListenUriInfo.Add(listenUriInfo, new StuffPerListenUriInfo()); } stuffPerListenUriInfo[listenUriInfo].Endpoints.Add(endpoint); stuffPerListenUriInfo[listenUriInfo].Parameters.Add(services); } 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); // add service-level binding parameters foreach (IServiceBehavior behavior in description.Behaviors) { 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.Format(SR.ABindingInstanceHasAlreadyBeenAssociatedTo1, viaString))); } // ensure all endpoints with this ListenUriInfo have same identity if (!Equals(endpoint.Address.Identity, identity)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR.Format(SR.SFxWhenMultipleEndpointsShareAListenUriTheyMustHaveSameIdentity, viaString))); } // add binding parameters (endpoint scope and below) AddBindingParametersForSecurityContractInformation(endpoint, parameters); AddBindingParameters(endpoint, parameters); } List <Type> channelTypes = GetSupportedChannelTypes(stuff.Value); var bindingQname = new XmlQualifiedName(binding.Name, binding.Namespace); var channelDispatcher = new ChannelDispatcher(listenUri, binding, bindingQname.ToString(), binding, channelTypes); //channelDispatcher.SetEndpointAddressTable(endpointAddressTable); stuff.Value.ChannelDispatcher = channelDispatcher; 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 = BuildEndpointDispatcher(description, endpoint); if (!endpointInfosPerEndpointAddress.ContainsKey(endpoint.Address)) { endpointInfosPerEndpointAddress.Add(endpoint.Address, new Collection <EndpointInfo>()); } endpointInfosPerEndpointAddress[endpoint.Address].Add(new EndpointInfo(endpoint, dispatcher, /*provider*/ null)); channelDispatcher.Endpoints.Add(dispatcher); } // end foreach "endpoint" 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 ApplyBindingInformationFromEndpointToDispatcher(endpoint, dispatcher); for (int j = 0; j < endpoint.Behaviors.Count; j++) { IEndpointBehavior eb = endpoint.Behaviors[j]; eb.ApplyDispatchBehavior(endpoint, dispatcher); } // run operation behaviors BindOperations(endpoint.Contract, null, dispatcher.DispatchRuntime); } } 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 if (iProvider != null && jProvider != null && HaveCommonInitiatingActions(iProvider, jProvider, out string commonAction)) { // you will definitely get a MultipleFiltersMatchedException at runtime, // so let's go ahead and throw now throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException( SR.Format(SR.SFxDuplicateInitiatingActionAtSameVia, endpointInfos[i].Endpoint.ListenUri, commonAction))); } } } } } } }
public EndpointInfo(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher, EndpointFilterProvider provider) { Endpoint = endpoint; EndpointDispatcher = endpointDispatcher; FilterProvider = provider; }
internal static ListenUriInfo GetListenUriInfoForEndpoint(ServiceHostBase host, ServiceEndpoint endpoint) { Uri listenUri = EnsureListenUri(host, endpoint); return(new ListenUriInfo(listenUri, endpoint.ListenUriMode)); }