// Helper method to validate that service contract T is correct. // This helper uses ClientBase<T> to construct the ContractDescription. // The 'expectedOperations' describes the operations we expect to find in that contract. public static string ValidateContractDescription <T>(ContractDescriptionData expectedContract) where T : class { OperationDescriptionData[] expectedOperations = expectedContract.Operations; StringBuilder errorBuilder = new StringBuilder(); try { // Arrange CustomBinding binding = new CustomBinding(); binding.Elements.Add(new TextMessageEncodingBindingElement()); binding.Elements.Add(new HttpTransportBindingElement()); EndpointAddress address = new EndpointAddress(FakeAddress.HttpAddress); // Act ChannelFactory <T> factory = new ChannelFactory <T>(binding, address); ContractDescription contract = factory.Endpoint.Contract; // Assert string results = ValidateContractDescription(contract, typeof(T), expectedContract); if (results != null) { errorBuilder.AppendLine(results); } } catch (Exception ex) { errorBuilder.AppendLine(String.Format("Unexpected exception was caught: {0}", ex.ToString())); } return(errorBuilder.Length == 0 ? null : errorBuilder.ToString()); }
// Helper method to validate that service contract T is correct. // This helper uses ClientBase<T> to construct the ContractDescription. // The 'expectedOperations' describes the operations we expect to find in that contract. public static string ValidateContractDescription <T>(ContractDescriptionData expectedContract) where T : class { OperationDescriptionData[] expectedOperations = expectedContract.Operations; StringBuilder errorBuilder = new StringBuilder(); try { CustomBinding customBinding = new CustomBinding(); customBinding.Elements.Add(new TextMessageEncodingBindingElement()); customBinding.Elements.Add(new HttpTransportBindingElement()); MyClientBase <T> client = new MyClientBase <T>(customBinding, new EndpointAddress(address)); ContractDescription contract = client.Endpoint.Contract; string results = ValidateContractDescription(contract, typeof(T), expectedContract); if (results != null) { errorBuilder.AppendLine(results); } } catch (Exception ex) { errorBuilder.AppendLine(String.Format("Unexpected exception was caught: {0}", ex.ToString())); } return(errorBuilder.Length == 0 ? null : errorBuilder.ToString()); }
// Helper method to validate the given ContractDescription has the expected type and operations. public static string ValidateContractDescription(ContractDescription contract, Type expectedType, ContractDescriptionData expectedContract) { OperationDescriptionData[] expectedOperations = expectedContract.Operations; #if DEBUGGING DumpContractDescription(contract); #endif StringBuilder errorBuilder = new StringBuilder(); string prefix = String.Format(" Contract type: {0}", expectedType); try { // ContractType must match expected type Type contractType = contract.ContractType; if (!expectedType.Equals(contractType)) { errorBuilder.AppendLine(String.Format("{0} expected Type = {0}, actual = {1}", prefix, expectedType, contractType)); } // Must have exactly the expected number of OperationDescriptions OperationDescriptionCollection ops = contract.Operations; if (ops.Count != expectedOperations.Length) { errorBuilder.AppendLine(String.Format("{0} operations.Count: expected={1}, actual = {2}", prefix, expectedOperations.Length, ops.Count)); } foreach (OperationDescriptionData expectedOp in expectedOperations) { // Must have each operation by name OperationDescription op = ops.Find(expectedOp.Name); if (op == null) { errorBuilder.AppendLine(String.Format("{0} operations: could not find operation {1}", prefix, expectedOp.Name)); } else { // Has expected operation name if (!op.Name.Equals(expectedOp.Name)) { errorBuilder.AppendLine(String.Format("{0} expected operation Name = {1}, actual = {2}", prefix, expectedOp.Name, op.Name)); } // Has expected one-way setting if (op.IsOneWay != expectedOp.IsOneWay) { errorBuilder.AppendLine(String.Format("{0} expected operation {1}.IsOneWay = {2}, actual = {3}", prefix, expectedOp.Name, expectedOp.IsOneWay, op.IsOneWay)); } // If contains XxxAsync operation, op.TaskMethod will be non-null. Verify it as expected. bool hasTask = op.TaskMethod != null; if (hasTask != expectedOp.HasTask) { errorBuilder.AppendLine(String.Format("{0} expected operation {1}.HasTask = {2}, actual = {3}", prefix, expectedOp.Name, expectedOp.HasTask, hasTask)); } // Validate each MessageDescription for each OperationDescription MessageDescriptionCollection messages = op.Messages; foreach (MessageDescriptionData messageData in expectedOp.Messages) { // Must find each expected MessageDescription by Action name MessageDescription messageDesc = messages.FirstOrDefault(m => m.Action.Equals(messageData.Action)); if (messageDesc == null) { errorBuilder.AppendLine(String.Format("{0} could not find expected message action {1} in operation {2}", prefix, messageData.Action, op.Name)); } else { // Must have expected direction if (messageDesc.Direction != messageData.Direction) { errorBuilder.AppendLine(String.Format("{0} message action {1} expected Direction = {2}, actual = {3}", prefix, messageData.Action, messageData.Direction, messageDesc.Direction)); } // MessageType is non-null for operations containing MessageContract types. // Verify we were able to build a "typed message" from the MessageContract. if (messageData.MessageType != null && !messageData.MessageType.Equals(messageDesc.MessageType)) { errorBuilder.AppendLine(String.Format("{0} message action {1} expected MessageType = {2}, actual = {3}", prefix, messageData.Action, messageData.MessageType, messageDesc.MessageType)); } } } } } } catch (Exception ex) { errorBuilder.AppendLine(String.Format("{0} unexpected exception was caught: {1}", prefix, ex.ToString())); } return(errorBuilder.Length == 0 ? null : errorBuilder.ToString()); }