public static void ComputeContractRequirements(ContractDescription contractDescription, out ChannelRequirements requirements) { requirements = new ChannelRequirements(); requirements.usesInput = false; requirements.usesReply = false; requirements.usesOutput = false; requirements.usesRequest = false; requirements.sessionMode = contractDescription.SessionMode; for (int i = 0; i < contractDescription.Operations.Count; i++) { OperationDescription description = contractDescription.Operations[i]; bool isOneWay = description.IsOneWay; if (!description.IsServerInitiated()) { if (isOneWay) { requirements.usesInput = true; } else { requirements.usesReply = true; } } else if (isOneWay) { requirements.usesOutput = true; } else { requirements.usesRequest = true; } } }
public static void ComputeContractRequirements(ContractDescription contractDescription, out ChannelRequirements requirements) { requirements = new ChannelRequirements(); requirements.usesInput = false; requirements.usesReply = false; requirements.usesOutput = false; requirements.usesRequest = false; requirements.sessionMode = contractDescription.SessionMode; for (int i = 0; i < contractDescription.Operations.Count; i++) { OperationDescription description = contractDescription.Operations[i]; bool isOneWay = description.IsOneWay; if (!description.IsServerInitiated()) { if (isOneWay) { requirements.usesInput = true; } else { requirements.usesReply = true; } } else if (isOneWay) { requirements.usesOutput = true; } else { requirements.usesRequest = true; } } }
public static Exception CantCreateChannelException(IEnumerable <Type> supportedChannels, IEnumerable <Type> requiredChannels, string bindingName) { string contractChannelTypesString = ""; string bindingChannelTypesString = ""; Exception exception = ChannelRequirements.BindingContractMismatchException(supportedChannels, requiredChannels, bindingName, ref contractChannelTypesString, ref bindingChannelTypesString); if (exception == null) { // none of the obvious speculations about the failure holds, so we fall back to the generic error message exception = new InvalidOperationException(SR.Format(SR.CouldnTCreateChannelForType2, bindingName, contractChannelTypesString)); } return(exception); }
public static Type[] ComputeRequiredChannels(ref ChannelRequirements requirements) { if (requirements.usesOutput || requirements.usesRequest) { switch (requirements.sessionMode) { case SessionMode.Allowed: return new Type[] { typeof(IDuplexChannel), typeof(IDuplexSessionChannel), }; case SessionMode.Required: return new Type[] { typeof(IDuplexSessionChannel), }; case SessionMode.NotAllowed: return new Type[] { typeof(IDuplexChannel), }; } } else if (requirements.usesInput && requirements.usesReply) { switch (requirements.sessionMode) { case SessionMode.Allowed: return new Type[] { typeof(IRequestChannel), typeof(IRequestSessionChannel), typeof(IDuplexChannel), typeof(IDuplexSessionChannel), }; case SessionMode.Required: return new Type[] { typeof(IRequestSessionChannel), typeof(IDuplexSessionChannel), }; case SessionMode.NotAllowed: return new Type[] { typeof(IRequestChannel), typeof(IDuplexChannel), }; } } else if (requirements.usesInput) { switch (requirements.sessionMode) { case SessionMode.Allowed: return new Type[] { typeof(IOutputChannel), typeof(IOutputSessionChannel), typeof(IRequestChannel), typeof(IRequestSessionChannel), typeof(IDuplexChannel), typeof(IDuplexSessionChannel), }; case SessionMode.Required: return new Type[] { typeof(IOutputSessionChannel), typeof(IRequestSessionChannel), typeof(IDuplexSessionChannel), }; case SessionMode.NotAllowed: return new Type[] { typeof(IOutputChannel), typeof(IRequestChannel), typeof(IDuplexChannel), }; } } else if (requirements.usesReply) { switch (requirements.sessionMode) { case SessionMode.Allowed: return new Type[] { typeof(IRequestChannel), typeof(IRequestSessionChannel), typeof(IDuplexChannel), typeof(IDuplexSessionChannel), }; case SessionMode.Required: return new Type[] { typeof(IRequestSessionChannel), typeof(IDuplexSessionChannel), }; case SessionMode.NotAllowed: return new Type[] { typeof(IRequestChannel), typeof(IDuplexChannel), }; } } else { switch (requirements.sessionMode) { case SessionMode.Allowed: return new Type[] { typeof(IOutputSessionChannel), typeof(IOutputChannel), typeof(IRequestSessionChannel), typeof(IRequestChannel), typeof(IDuplexChannel), typeof(IDuplexSessionChannel), }; case SessionMode.Required: return new Type[] { typeof(IOutputSessionChannel), typeof(IRequestSessionChannel), typeof(IDuplexSessionChannel), }; case SessionMode.NotAllowed: return new Type[] { typeof(IOutputChannel), typeof(IRequestChannel), typeof(IDuplexChannel), }; } } return null; }
public static System.Type[] ComputeRequiredChannels(ref ChannelRequirements requirements) { if (requirements.usesOutput || requirements.usesRequest) { switch (requirements.sessionMode) { case SessionMode.Allowed: return(new System.Type[] { typeof(IDuplexChannel), typeof(IDuplexSessionChannel) }); case SessionMode.Required: return(new System.Type[] { typeof(IDuplexSessionChannel) }); case SessionMode.NotAllowed: return(new System.Type[] { typeof(IDuplexChannel) }); } } else if (requirements.usesInput && requirements.usesReply) { switch (requirements.sessionMode) { case SessionMode.Allowed: return(new System.Type[] { typeof(IRequestChannel), typeof(IRequestSessionChannel), typeof(IDuplexChannel), typeof(IDuplexSessionChannel) }); case SessionMode.Required: return(new System.Type[] { typeof(IRequestSessionChannel), typeof(IDuplexSessionChannel) }); case SessionMode.NotAllowed: return(new System.Type[] { typeof(IRequestChannel), typeof(IDuplexChannel) }); } } else if (requirements.usesInput) { switch (requirements.sessionMode) { case SessionMode.Allowed: return(new System.Type[] { typeof(IOutputChannel), typeof(IOutputSessionChannel), typeof(IRequestChannel), typeof(IRequestSessionChannel), typeof(IDuplexChannel), typeof(IDuplexSessionChannel) }); case SessionMode.Required: return(new System.Type[] { typeof(IOutputSessionChannel), typeof(IRequestSessionChannel), typeof(IDuplexSessionChannel) }); case SessionMode.NotAllowed: return(new System.Type[] { typeof(IOutputChannel), typeof(IRequestChannel), typeof(IDuplexChannel) }); } } else if (requirements.usesReply) { switch (requirements.sessionMode) { case SessionMode.Allowed: return(new System.Type[] { typeof(IRequestChannel), typeof(IRequestSessionChannel), typeof(IDuplexChannel), typeof(IDuplexSessionChannel) }); case SessionMode.Required: return(new System.Type[] { typeof(IRequestSessionChannel), typeof(IDuplexSessionChannel) }); case SessionMode.NotAllowed: return(new System.Type[] { typeof(IRequestChannel), typeof(IDuplexChannel) }); } } else { switch (requirements.sessionMode) { case SessionMode.Allowed: return(new System.Type[] { typeof(IOutputSessionChannel), typeof(IOutputChannel), typeof(IRequestSessionChannel), typeof(IRequestChannel), typeof(IDuplexChannel), typeof(IDuplexSessionChannel) }); case SessionMode.Required: return(new System.Type[] { typeof(IOutputSessionChannel), typeof(IRequestSessionChannel), typeof(IDuplexSessionChannel) }); case SessionMode.NotAllowed: return(new System.Type[] { typeof(IOutputChannel), typeof(IRequestChannel), typeof(IDuplexChannel) }); } } return(null); }
public static ServiceChannelFactory BuildChannelFactory(ServiceEndpoint serviceEndpoint, bool useActiveAutoClose) { if (serviceEndpoint == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceEndpoint"); } serviceEndpoint.EnsureInvariants(); serviceEndpoint.ValidateForClient(); ChannelRequirements requirements; ContractDescription contractDescription = serviceEndpoint.Contract; ChannelRequirements.ComputeContractRequirements(contractDescription, out requirements); BindingParameterCollection parameters; ClientRuntime clientRuntime = DispatcherBuilder.BuildProxyBehavior(serviceEndpoint, out parameters); Binding binding = serviceEndpoint.Binding; Type[] requiredChannels = ChannelRequirements.ComputeRequiredChannels(ref requirements); CustomBinding customBinding = new CustomBinding(binding); BindingContext context = new BindingContext(customBinding, parameters); InternalDuplexBindingElement internalDuplexBindingElement = null; InternalDuplexBindingElement.AddDuplexFactorySupport(context, ref internalDuplexBindingElement); customBinding = new CustomBinding(context.RemainingBindingElements); customBinding.CopyTimeouts(serviceEndpoint.Binding); foreach (Type type in requiredChannels) { if (type == typeof(IOutputChannel) && customBinding.CanBuildChannelFactory <IOutputChannel>(parameters)) { return(new ServiceChannelFactoryOverOutput(customBinding.BuildChannelFactory <IOutputChannel>(parameters), clientRuntime, binding)); } if (type == typeof(IRequestChannel) && customBinding.CanBuildChannelFactory <IRequestChannel>(parameters)) { return(new ServiceChannelFactoryOverRequest(customBinding.BuildChannelFactory <IRequestChannel>(parameters), clientRuntime, binding)); } if (type == typeof(IDuplexChannel) && customBinding.CanBuildChannelFactory <IDuplexChannel>(parameters)) { if (requirements.usesReply && binding.CreateBindingElements().Find <TransportBindingElement>().ManualAddressing) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR.GetString(SR.CantCreateChannelWithManualAddressing))); } return(new ServiceChannelFactoryOverDuplex(customBinding.BuildChannelFactory <IDuplexChannel>(parameters), clientRuntime, binding)); } if (type == typeof(IOutputSessionChannel) && customBinding.CanBuildChannelFactory <IOutputSessionChannel>(parameters)) { return(new ServiceChannelFactoryOverOutputSession(customBinding.BuildChannelFactory <IOutputSessionChannel>(parameters), clientRuntime, binding, false)); } if (type == typeof(IRequestSessionChannel) && customBinding.CanBuildChannelFactory <IRequestSessionChannel>(parameters)) { return(new ServiceChannelFactoryOverRequestSession(customBinding.BuildChannelFactory <IRequestSessionChannel>(parameters), clientRuntime, binding, false)); } if (type == typeof(IDuplexSessionChannel) && customBinding.CanBuildChannelFactory <IDuplexSessionChannel>(parameters)) { if (requirements.usesReply && binding.CreateBindingElements().Find <TransportBindingElement>().ManualAddressing) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR.GetString(SR.CantCreateChannelWithManualAddressing))); } return(new ServiceChannelFactoryOverDuplexSession(customBinding.BuildChannelFactory <IDuplexSessionChannel>(parameters), clientRuntime, binding, useActiveAutoClose)); } } foreach (Type type in requiredChannels) { // For SessionMode.Allowed or SessionMode.NotAllowed we will accept session-ful variants as well if (type == typeof(IOutputChannel) && customBinding.CanBuildChannelFactory <IOutputSessionChannel>(parameters)) { return(new ServiceChannelFactoryOverOutputSession(customBinding.BuildChannelFactory <IOutputSessionChannel>(parameters), clientRuntime, binding, true)); } if (type == typeof(IRequestChannel) && customBinding.CanBuildChannelFactory <IRequestSessionChannel>(parameters)) { return(new ServiceChannelFactoryOverRequestSession(customBinding.BuildChannelFactory <IRequestSessionChannel>(parameters), clientRuntime, binding, true)); } // and for SessionMode.Required, it is possible that the InstanceContextProvider is handling the session management, so // accept datagram variants if that is the case if (type == typeof(IRequestSessionChannel) && customBinding.CanBuildChannelFactory <IRequestChannel>(parameters) && customBinding.GetProperty <IContextSessionProvider>(parameters) != null) { return(new ServiceChannelFactoryOverRequest(customBinding.BuildChannelFactory <IRequestChannel>(parameters), clientRuntime, binding)); } } // we put a lot of work into creating a good error message, as this is a common case Dictionary <Type, byte> supportedChannels = new Dictionary <Type, byte>(); if (customBinding.CanBuildChannelFactory <IOutputChannel>(parameters)) { supportedChannels.Add(typeof(IOutputChannel), 0); } if (customBinding.CanBuildChannelFactory <IRequestChannel>(parameters)) { supportedChannels.Add(typeof(IRequestChannel), 0); } if (customBinding.CanBuildChannelFactory <IDuplexChannel>(parameters)) { supportedChannels.Add(typeof(IDuplexChannel), 0); } if (customBinding.CanBuildChannelFactory <IOutputSessionChannel>(parameters)) { supportedChannels.Add(typeof(IOutputSessionChannel), 0); } if (customBinding.CanBuildChannelFactory <IRequestSessionChannel>(parameters)) { supportedChannels.Add(typeof(IRequestSessionChannel), 0); } if (customBinding.CanBuildChannelFactory <IDuplexSessionChannel>(parameters)) { supportedChannels.Add(typeof(IDuplexSessionChannel), 0); } throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ChannelRequirements.CantCreateChannelException( supportedChannels.Keys, requiredChannels, binding.Name)); }
public static Exception BindingContractMismatchException(IEnumerable <Type> supportedChannels, IEnumerable <Type> requiredChannels, string bindingName, ref string contractChannelTypesString, ref string bindingChannelTypesString) { StringBuilder contractChannelTypes = new StringBuilder(); bool contractRequiresOneWay = true; bool contractRequiresRequestReply = true; bool contractRequiresDuplex = true; bool contractRequiresTwoWay = true; // request-reply or duplex bool contractRequiresSession = true; bool contractRequiresDatagram = true; foreach (Type channelType in requiredChannels) { if (contractChannelTypes.Length > 0) { contractChannelTypes.Append(CultureInfo.CurrentCulture.TextInfo.ListSeparator); contractChannelTypes.Append(" "); } string typeString = channelType.ToString(); contractChannelTypes.Append(typeString.Substring(typeString.LastIndexOf('.') + 1)); if (!ChannelRequirements.IsOneWay(channelType)) { contractRequiresOneWay = false; } if (!ChannelRequirements.IsRequestReply(channelType)) { contractRequiresRequestReply = false; } if (!ChannelRequirements.IsDuplex(channelType)) { contractRequiresDuplex = false; } if (!(ChannelRequirements.IsRequestReply(channelType) || ChannelRequirements.IsDuplex(channelType))) { contractRequiresTwoWay = false; } if (!ChannelRequirements.IsSessionful(channelType)) { contractRequiresSession = false; } else { contractRequiresDatagram = false; } } StringBuilder bindingChannelTypes = new StringBuilder(); bool bindingSupportsOneWay = false; bool bindingSupportsRequestReply = false; bool bindingSupportsDuplex = false; bool bindingSupportsSession = false; bool bindingSupportsDatagram = false; bool bindingSupportsAtLeastOneChannelType = false; foreach (Type channelType in supportedChannels) { bindingSupportsAtLeastOneChannelType = true; if (bindingChannelTypes.Length > 0) { bindingChannelTypes.Append(CultureInfo.CurrentCulture.TextInfo.ListSeparator); bindingChannelTypes.Append(" "); } string typeString = channelType.ToString(); bindingChannelTypes.Append(typeString.Substring(typeString.LastIndexOf('.') + 1)); if (ChannelRequirements.IsOneWay(channelType)) { bindingSupportsOneWay = true; } if (ChannelRequirements.IsRequestReply(channelType)) { bindingSupportsRequestReply = true; } if (ChannelRequirements.IsDuplex(channelType)) { bindingSupportsDuplex = true; } if (ChannelRequirements.IsSessionful(channelType)) { bindingSupportsSession = true; } else { bindingSupportsDatagram = true; } } bool bindingSupportsTwoWay = bindingSupportsRequestReply || bindingSupportsDuplex; if (!bindingSupportsAtLeastOneChannelType) { return(new InvalidOperationException(SR.Format(SR.BindingDoesnTSupportAnyChannelTypes1, bindingName))); } if (contractRequiresSession && !bindingSupportsSession) { return(new InvalidOperationException(SR.Format(SR.BindingDoesnTSupportSessionButContractRequires1, bindingName))); } if (contractRequiresDatagram && !bindingSupportsDatagram) { return(new InvalidOperationException(SR.Format(SR.BindingDoesntSupportDatagramButContractRequires, bindingName))); } if (contractRequiresDuplex && !bindingSupportsDuplex) { return(new InvalidOperationException(SR.Format(SR.BindingDoesnTSupportDuplexButContractRequires1, bindingName))); } if (contractRequiresRequestReply && !bindingSupportsRequestReply) { return(new InvalidOperationException(SR.Format(SR.BindingDoesnTSupportRequestReplyButContract1, bindingName))); } if (contractRequiresOneWay && !bindingSupportsOneWay) { return(new InvalidOperationException(SR.Format(SR.BindingDoesnTSupportOneWayButContractRequires1, bindingName))); } if (contractRequiresTwoWay && !bindingSupportsTwoWay) { return(new InvalidOperationException(SR.Format(SR.BindingDoesnTSupportTwoWayButContractRequires1, bindingName))); } contractChannelTypesString = contractChannelTypes.ToString(); bindingChannelTypesString = bindingChannelTypes.ToString(); return(null); }
public static ServiceChannelFactory BuildChannelFactory(ServiceEndpoint serviceEndpoint, bool useActiveAutoClose) { ChannelRequirements requirements; BindingParameterCollection parameters; if (serviceEndpoint == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceEndpoint"); } serviceEndpoint.EnsureInvariants(); serviceEndpoint.ValidateForClient(); ChannelRequirements.ComputeContractRequirements(serviceEndpoint.Contract, out requirements); System.ServiceModel.Dispatcher.ClientRuntime clientRuntime = DispatcherBuilder.BuildProxyBehavior(serviceEndpoint, out parameters); Binding binding = serviceEndpoint.Binding; System.Type[] requiredChannels = ChannelRequirements.ComputeRequiredChannels(ref requirements); CustomBinding binding2 = new CustomBinding(binding); BindingContext context = new BindingContext(binding2, parameters); InternalDuplexBindingElement internalDuplexBindingElement = null; InternalDuplexBindingElement.AddDuplexFactorySupport(context, ref internalDuplexBindingElement); binding2 = new CustomBinding(context.RemainingBindingElements); binding2.CopyTimeouts(serviceEndpoint.Binding); foreach (System.Type type in requiredChannels) { if ((type == typeof(IOutputChannel)) && binding2.CanBuildChannelFactory <IOutputChannel>(parameters)) { return(new ServiceChannelFactoryOverOutput(binding2.BuildChannelFactory <IOutputChannel>(parameters), clientRuntime, binding)); } if ((type == typeof(IRequestChannel)) && binding2.CanBuildChannelFactory <IRequestChannel>(parameters)) { return(new ServiceChannelFactoryOverRequest(binding2.BuildChannelFactory <IRequestChannel>(parameters), clientRuntime, binding)); } if ((type == typeof(IDuplexChannel)) && binding2.CanBuildChannelFactory <IDuplexChannel>(parameters)) { if (requirements.usesReply && binding.CreateBindingElements().Find <TransportBindingElement>().ManualAddressing) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("CantCreateChannelWithManualAddressing"))); } return(new ServiceChannelFactoryOverDuplex(binding2.BuildChannelFactory <IDuplexChannel>(parameters), clientRuntime, binding)); } if ((type == typeof(IOutputSessionChannel)) && binding2.CanBuildChannelFactory <IOutputSessionChannel>(parameters)) { return(new ServiceChannelFactoryOverOutputSession(binding2.BuildChannelFactory <IOutputSessionChannel>(parameters), clientRuntime, binding, false)); } if ((type == typeof(IRequestSessionChannel)) && binding2.CanBuildChannelFactory <IRequestSessionChannel>(parameters)) { return(new ServiceChannelFactoryOverRequestSession(binding2.BuildChannelFactory <IRequestSessionChannel>(parameters), clientRuntime, binding, false)); } if ((type == typeof(IDuplexSessionChannel)) && binding2.CanBuildChannelFactory <IDuplexSessionChannel>(parameters)) { if (requirements.usesReply && binding.CreateBindingElements().Find <TransportBindingElement>().ManualAddressing) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("CantCreateChannelWithManualAddressing"))); } return(new ServiceChannelFactoryOverDuplexSession(binding2.BuildChannelFactory <IDuplexSessionChannel>(parameters), clientRuntime, binding, useActiveAutoClose)); } } foreach (System.Type type2 in requiredChannels) { if ((type2 == typeof(IOutputChannel)) && binding2.CanBuildChannelFactory <IOutputSessionChannel>(parameters)) { return(new ServiceChannelFactoryOverOutputSession(binding2.BuildChannelFactory <IOutputSessionChannel>(parameters), clientRuntime, binding, true)); } if ((type2 == typeof(IRequestChannel)) && binding2.CanBuildChannelFactory <IRequestSessionChannel>(parameters)) { return(new ServiceChannelFactoryOverRequestSession(binding2.BuildChannelFactory <IRequestSessionChannel>(parameters), clientRuntime, binding, true)); } if (((type2 == typeof(IRequestSessionChannel)) && binding2.CanBuildChannelFactory <IRequestChannel>(parameters)) && (binding2.GetProperty <IContextSessionProvider>(parameters) != null)) { return(new ServiceChannelFactoryOverRequest(binding2.BuildChannelFactory <IRequestChannel>(parameters), clientRuntime, binding)); } } Dictionary <System.Type, byte> dictionary = new Dictionary <System.Type, byte>(); if (binding2.CanBuildChannelFactory <IOutputChannel>(parameters)) { dictionary.Add(typeof(IOutputChannel), 0); } if (binding2.CanBuildChannelFactory <IRequestChannel>(parameters)) { dictionary.Add(typeof(IRequestChannel), 0); } if (binding2.CanBuildChannelFactory <IDuplexChannel>(parameters)) { dictionary.Add(typeof(IDuplexChannel), 0); } if (binding2.CanBuildChannelFactory <IOutputSessionChannel>(parameters)) { dictionary.Add(typeof(IOutputSessionChannel), 0); } if (binding2.CanBuildChannelFactory <IRequestSessionChannel>(parameters)) { dictionary.Add(typeof(IRequestSessionChannel), 0); } if (binding2.CanBuildChannelFactory <IDuplexSessionChannel>(parameters)) { dictionary.Add(typeof(IDuplexSessionChannel), 0); } throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ChannelRequirements.CantCreateChannelException(dictionary.Keys, requiredChannels, binding.Name)); }