709 lines
33 KiB
C#
709 lines
33 KiB
C#
|
//------------------------------------------------------------------------------
|
||
|
// <copyright file="ProtocolImporter.cs" company="Microsoft">
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
// </copyright>
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
namespace System.Web.Services.Description {
|
||
|
|
||
|
using System.Web.Services;
|
||
|
using System.Web.Services.Protocols;
|
||
|
using System.Xml.Serialization;
|
||
|
using System.Xml.Schema;
|
||
|
using System.Collections;
|
||
|
using System;
|
||
|
using System.Reflection;
|
||
|
using System.CodeDom;
|
||
|
using System.CodeDom.Compiler;
|
||
|
using System.Text;
|
||
|
using System.Xml;
|
||
|
using System.Web.Services.Configuration;
|
||
|
using System.Configuration;
|
||
|
using System.Security.Permissions;
|
||
|
using System.Threading;
|
||
|
using System.Diagnostics;
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")]
|
||
|
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
|
||
|
public abstract class ProtocolImporter {
|
||
|
ServiceDescriptionImporter importer;
|
||
|
CodeNamespace codeNamespace;
|
||
|
CodeIdentifiers methodNames;
|
||
|
CodeTypeDeclaration codeClass;
|
||
|
CodeTypeDeclarationCollection classes;
|
||
|
ServiceDescriptionImportWarnings warnings;
|
||
|
Port port;
|
||
|
PortType portType;
|
||
|
Binding binding;
|
||
|
Operation operation;
|
||
|
OperationBinding operationBinding;
|
||
|
bool encodedBinding;
|
||
|
ImportContext importContext;
|
||
|
Hashtable exportContext;
|
||
|
Service service;
|
||
|
Message inputMessage;
|
||
|
Message outputMessage;
|
||
|
string className;
|
||
|
int bindingCount;
|
||
|
bool anyPorts;
|
||
|
|
||
|
internal void Initialize(ServiceDescriptionImporter importer) {
|
||
|
this.importer = importer;
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.ServiceDescriptions"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public ServiceDescriptionCollection ServiceDescriptions {
|
||
|
get { return importer.ServiceDescriptions; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.Schemas"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public XmlSchemas Schemas {
|
||
|
get { return importer.AllSchemas; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.AbstractSchemas"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public XmlSchemas AbstractSchemas {
|
||
|
get { return importer.AbstractSchemas; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.ConcreteSchemas"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public XmlSchemas ConcreteSchemas {
|
||
|
get { return importer.ConcreteSchemas; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.CodeNamespace"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public CodeNamespace CodeNamespace {
|
||
|
get { return codeNamespace; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.CodeTypeDeclaration"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public CodeTypeDeclaration CodeTypeDeclaration {
|
||
|
get { return codeClass; }
|
||
|
}
|
||
|
|
||
|
internal CodeTypeDeclarationCollection ExtraCodeClasses {
|
||
|
get {
|
||
|
if (classes == null)
|
||
|
classes = new CodeTypeDeclarationCollection();
|
||
|
return classes;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.Style"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public ServiceDescriptionImportStyle Style {
|
||
|
get { return importer.Style; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.Warnings"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public ServiceDescriptionImportWarnings Warnings {
|
||
|
get { return warnings; }
|
||
|
set { warnings = value; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.ClassNames"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public CodeIdentifiers ClassNames {
|
||
|
get { return importContext.TypeIdentifiers; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.MethodName"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public string MethodName {
|
||
|
get {
|
||
|
// We don't attempt to make this unique because of method overloading
|
||
|
return CodeIdentifier.MakeValid(XmlConvert.DecodeName(Operation.Name));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.ClassName"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public string ClassName {
|
||
|
get { return className; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.Port"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public Port Port {
|
||
|
get { return port; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.PortType"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public PortType PortType {
|
||
|
get { return portType; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.Binding"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public Binding Binding {
|
||
|
get { return binding; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.Service"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public Service Service {
|
||
|
get { return service; }
|
||
|
}
|
||
|
|
||
|
internal ServiceDescriptionImporter ServiceImporter {
|
||
|
get { return importer; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.Operation"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public Operation Operation {
|
||
|
get { return operation; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.OperationBinding"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public OperationBinding OperationBinding {
|
||
|
get { return operationBinding; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.InputMessage"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public Message InputMessage {
|
||
|
get { return inputMessage; }
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.OutputMessage"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public Message OutputMessage {
|
||
|
get { return outputMessage; }
|
||
|
}
|
||
|
|
||
|
internal ImportContext ImportContext {
|
||
|
get { return importContext; }
|
||
|
}
|
||
|
|
||
|
internal bool IsEncodedBinding {
|
||
|
get { return encodedBinding; }
|
||
|
set { encodedBinding = value; }
|
||
|
}
|
||
|
|
||
|
internal Hashtable ExportContext {
|
||
|
get {
|
||
|
if (exportContext == null)
|
||
|
exportContext = new Hashtable();
|
||
|
return exportContext;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal CodeIdentifiers MethodNames {
|
||
|
get {
|
||
|
if (methodNames == null)
|
||
|
methodNames = new CodeIdentifiers();
|
||
|
return methodNames;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool GenerateCode(CodeNamespace codeNamespace, ImportContext importContext, Hashtable exportContext) {
|
||
|
bindingCount = 0;
|
||
|
anyPorts = false;
|
||
|
|
||
|
this.codeNamespace = codeNamespace;
|
||
|
|
||
|
Hashtable supportedBindings = new Hashtable();
|
||
|
Hashtable unsupportedBindings = new Hashtable();
|
||
|
|
||
|
// look for ports with bindings
|
||
|
foreach (ServiceDescription serviceDescription in ServiceDescriptions) {
|
||
|
foreach (Service service in serviceDescription.Services) {
|
||
|
foreach (Port port in service.Ports) {
|
||
|
Binding binding = ServiceDescriptions.GetBinding(port.Binding);
|
||
|
if (supportedBindings.Contains(binding))
|
||
|
continue;
|
||
|
PortType portType = ServiceDescriptions.GetPortType(binding.Type);
|
||
|
MoveToBinding(service, port, binding, portType);
|
||
|
if (IsBindingSupported()) {
|
||
|
bindingCount++;
|
||
|
anyPorts = true;
|
||
|
supportedBindings.Add(binding, binding);
|
||
|
}
|
||
|
else if (binding != null) unsupportedBindings[binding] = binding;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// no ports, look for bindings
|
||
|
if (bindingCount == 0) {
|
||
|
foreach (ServiceDescription serviceDescription in ServiceDescriptions) {
|
||
|
foreach (Binding binding in serviceDescription.Bindings) {
|
||
|
if (unsupportedBindings.Contains(binding)) continue;
|
||
|
PortType portType = ServiceDescriptions.GetPortType(binding.Type);
|
||
|
MoveToBinding(binding, portType);
|
||
|
if (IsBindingSupported()) {
|
||
|
bindingCount++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// give up if no bindings
|
||
|
if (bindingCount == 0) {
|
||
|
// if we generated comments return true so that the comments get written
|
||
|
return codeNamespace.Comments.Count > 0;
|
||
|
}
|
||
|
|
||
|
this.importContext = importContext;
|
||
|
this.exportContext = exportContext;
|
||
|
BeginNamespace();
|
||
|
|
||
|
supportedBindings.Clear();
|
||
|
foreach (ServiceDescription serviceDescription in ServiceDescriptions) {
|
||
|
if (anyPorts) {
|
||
|
foreach (Service service in serviceDescription.Services) {
|
||
|
foreach (Port port in service.Ports) {
|
||
|
Binding binding = ServiceDescriptions.GetBinding(port.Binding);
|
||
|
PortType portType = ServiceDescriptions.GetPortType(binding.Type);
|
||
|
MoveToBinding(service, port, binding, portType);
|
||
|
if (IsBindingSupported() && !supportedBindings.Contains(binding)) {
|
||
|
GenerateClassForBinding();
|
||
|
supportedBindings.Add(binding, binding);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
foreach (Binding binding in serviceDescription.Bindings) {
|
||
|
PortType portType = ServiceDescriptions.GetPortType(binding.Type);
|
||
|
MoveToBinding(binding, portType);
|
||
|
if (IsBindingSupported()) {
|
||
|
GenerateClassForBinding();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
EndNamespace();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void MoveToBinding(Binding binding, PortType portType) {
|
||
|
MoveToBinding(null, null, binding, portType);
|
||
|
}
|
||
|
|
||
|
void MoveToBinding(Service service, Port port, Binding binding, PortType portType) {
|
||
|
this.service = service;
|
||
|
this.port = port;
|
||
|
this.portType = portType;
|
||
|
this.binding = binding;
|
||
|
this.encodedBinding = false;
|
||
|
}
|
||
|
|
||
|
void MoveToOperation(Operation operation) {
|
||
|
this.operation = operation;
|
||
|
|
||
|
operationBinding = null;
|
||
|
foreach (OperationBinding b in binding.Operations) {
|
||
|
if (operation.IsBoundBy(b)) {
|
||
|
if (operationBinding != null) throw OperationSyntaxException(Res.GetString(Res.DuplicateInputOutputNames0));
|
||
|
operationBinding = b;
|
||
|
}
|
||
|
}
|
||
|
if (operationBinding == null) {
|
||
|
throw OperationSyntaxException(Res.GetString(Res.MissingBinding0));
|
||
|
}
|
||
|
//NOTE: The following two excepions would never happen since IsBoundBy checks these conditions already.
|
||
|
if (operation.Messages.Input != null && operationBinding.Input == null) {
|
||
|
throw OperationSyntaxException(Res.GetString(Res.MissingInputBinding0));
|
||
|
}
|
||
|
if (operation.Messages.Output != null && operationBinding.Output == null) {
|
||
|
throw OperationSyntaxException(Res.GetString(Res.MissingOutputBinding0));
|
||
|
}
|
||
|
|
||
|
this.inputMessage = operation.Messages.Input == null ? null : ServiceDescriptions.GetMessage(operation.Messages.Input.Message);
|
||
|
this.outputMessage = operation.Messages.Output == null ? null : ServiceDescriptions.GetMessage(operation.Messages.Output.Message);
|
||
|
}
|
||
|
|
||
|
void GenerateClassForBinding() {
|
||
|
try {
|
||
|
if (bindingCount == 1 && service != null && Style != ServiceDescriptionImportStyle.ServerInterface) {
|
||
|
// If there is only one binding, then use the name of the service
|
||
|
className = XmlConvert.DecodeName(service.Name);
|
||
|
}
|
||
|
else {
|
||
|
// If multiple bindings, then use the name of the binding
|
||
|
className = binding.Name;
|
||
|
if (Style == ServiceDescriptionImportStyle.ServerInterface)
|
||
|
{
|
||
|
// append "I" if we are generating interfaces
|
||
|
className = "I" + CodeIdentifier.MakePascal(className);
|
||
|
}
|
||
|
}
|
||
|
className = XmlConvert.DecodeName(className);
|
||
|
className = ClassNames.AddUnique(CodeIdentifier.MakeValid(className), null);
|
||
|
this.codeClass = BeginClass();
|
||
|
int methodCount = 0;
|
||
|
for (int i = 0; i < portType.Operations.Count; i++) {
|
||
|
MoveToOperation(portType.Operations[i]);
|
||
|
|
||
|
if (!IsOperationFlowSupported(operation.Messages.Flow)) {
|
||
|
//
|
||
|
switch (operation.Messages.Flow) {
|
||
|
case OperationFlow.SolicitResponse:
|
||
|
UnsupportedOperationWarning(Res.GetString(Res.SolicitResponseIsNotSupported0));
|
||
|
continue;
|
||
|
case OperationFlow.RequestResponse:
|
||
|
UnsupportedOperationWarning(Res.GetString(Res.RequestResponseIsNotSupported0));
|
||
|
continue;
|
||
|
case OperationFlow.OneWay:
|
||
|
UnsupportedOperationWarning(Res.GetString(Res.OneWayIsNotSupported0));
|
||
|
continue;
|
||
|
case OperationFlow.Notification:
|
||
|
UnsupportedOperationWarning(Res.GetString(Res.NotificationIsNotSupported0));
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CodeMemberMethod method;
|
||
|
try {
|
||
|
method = GenerateMethod();
|
||
|
}
|
||
|
catch (Exception e) {
|
||
|
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
|
||
|
throw;
|
||
|
}
|
||
|
throw new InvalidOperationException(Res.GetString(Res.UnableToImportOperation1, operation.Name), e);
|
||
|
}
|
||
|
|
||
|
if (method != null) {
|
||
|
AddExtensionWarningComments(codeClass.Comments, operationBinding.Extensions);
|
||
|
if (operationBinding.Input != null) AddExtensionWarningComments(codeClass.Comments, operationBinding.Input.Extensions);
|
||
|
if (operationBinding.Output != null) AddExtensionWarningComments(codeClass.Comments, operationBinding.Output.Extensions);
|
||
|
methodCount++;
|
||
|
}
|
||
|
}
|
||
|
bool newAsync = (ServiceImporter.CodeGenerationOptions & CodeGenerationOptions.GenerateNewAsync) != 0 &&
|
||
|
ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareEvents) &&
|
||
|
ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareDelegates);
|
||
|
if (newAsync && methodCount > 0 && Style == ServiceDescriptionImportStyle.Client) {
|
||
|
CodeAttributeDeclarationCollection metadata = new CodeAttributeDeclarationCollection();
|
||
|
string cancelAsync = "CancelAsync";
|
||
|
string cancelMethodName = MethodNames.AddUnique(cancelAsync, cancelAsync);
|
||
|
CodeMemberMethod asyncCancelMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, cancelMethodName,
|
||
|
new CodeFlags[1], new string[] { typeof(object).FullName }, new string[] { "userState" },
|
||
|
typeof(void).FullName,
|
||
|
metadata,
|
||
|
CodeFlags.IsPublic | (cancelAsync != cancelMethodName ? 0 : CodeFlags.IsNew));
|
||
|
|
||
|
asyncCancelMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
|
||
|
CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(new CodeBaseReferenceExpression(), cancelAsync);
|
||
|
invoke.Parameters.Add(new CodeArgumentReferenceExpression("userState"));
|
||
|
asyncCancelMethod.Statements.Add(invoke);
|
||
|
}
|
||
|
|
||
|
EndClass();
|
||
|
|
||
|
if (portType.Operations.Count == 0)
|
||
|
NoMethodsGeneratedWarning();
|
||
|
|
||
|
AddExtensionWarningComments(codeClass.Comments, binding.Extensions);
|
||
|
if (port != null) AddExtensionWarningComments(codeClass.Comments, port.Extensions);
|
||
|
|
||
|
codeNamespace.Types.Add(codeClass);
|
||
|
}
|
||
|
catch (Exception e) {
|
||
|
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
|
||
|
throw;
|
||
|
}
|
||
|
throw new InvalidOperationException(Res.GetString(Res.UnableToImportBindingFromNamespace2, binding.Name, binding.ServiceDescription.TargetNamespace), e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.AddExtensionWarningComments"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public void AddExtensionWarningComments(CodeCommentStatementCollection comments, ServiceDescriptionFormatExtensionCollection extensions) {
|
||
|
foreach (object item in extensions) {
|
||
|
if (!extensions.IsHandled(item)) {
|
||
|
string name = null;
|
||
|
string ns = null;
|
||
|
if (item is XmlElement) {
|
||
|
XmlElement element = (XmlElement)item;
|
||
|
name = element.LocalName;
|
||
|
ns = element.NamespaceURI;
|
||
|
}
|
||
|
else if (item is ServiceDescriptionFormatExtension) {
|
||
|
XmlFormatExtensionAttribute[] attrs = (XmlFormatExtensionAttribute[])item.GetType().GetCustomAttributes(typeof(XmlFormatExtensionAttribute), false);
|
||
|
if (attrs.Length > 0) {
|
||
|
name = attrs[0].ElementName;
|
||
|
ns = attrs[0].Namespace;
|
||
|
}
|
||
|
}
|
||
|
if (name != null) {
|
||
|
if (extensions.IsRequired(item)) {
|
||
|
warnings |= ServiceDescriptionImportWarnings.RequiredExtensionsIgnored;
|
||
|
AddWarningComment(comments, Res.GetString(Res.WebServiceDescriptionIgnoredRequired, name, ns));
|
||
|
}
|
||
|
else {
|
||
|
warnings |= ServiceDescriptionImportWarnings.OptionalExtensionsIgnored;
|
||
|
AddWarningComment(comments, Res.GetString(Res.WebServiceDescriptionIgnoredOptional, name, ns));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.UnsupportedBindingWarning"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public void UnsupportedBindingWarning(string text) {
|
||
|
AddWarningComment(codeClass == null ? codeNamespace.Comments : codeClass.Comments, Res.GetString(Res.TheBinding0FromNamespace1WasIgnored2, Binding.Name, Binding.ServiceDescription.TargetNamespace, text));
|
||
|
warnings |= ServiceDescriptionImportWarnings.UnsupportedBindingsIgnored;
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.UnsupportedOperationWarning"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public void UnsupportedOperationWarning(string text) {
|
||
|
AddWarningComment(codeClass == null ? codeNamespace.Comments : codeClass.Comments, Res.GetString(Res.TheOperation0FromNamespace1WasIgnored2, operation.Name, operation.PortType.ServiceDescription.TargetNamespace, text));
|
||
|
warnings |= ServiceDescriptionImportWarnings.UnsupportedOperationsIgnored;
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.UnsupportedOperationBindingWarning"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public void UnsupportedOperationBindingWarning(string text) {
|
||
|
AddWarningComment(codeClass == null ? codeNamespace.Comments : codeClass.Comments, Res.GetString(Res.TheOperationBinding0FromNamespace1WasIgnored, operationBinding.Name, operationBinding.Binding.ServiceDescription.TargetNamespace, text));
|
||
|
warnings |= ServiceDescriptionImportWarnings.UnsupportedOperationsIgnored;
|
||
|
}
|
||
|
|
||
|
void NoMethodsGeneratedWarning() {
|
||
|
AddWarningComment(codeClass.Comments, Res.GetString(Res.NoMethodsWereFoundInTheWSDLForThisProtocol));
|
||
|
warnings |= ServiceDescriptionImportWarnings.NoMethodsGenerated;
|
||
|
}
|
||
|
|
||
|
internal static void AddWarningComment(CodeCommentStatementCollection comments, string text) {
|
||
|
comments.Add(new CodeCommentStatement(Res.GetString(Res.CodegenWarningDetails, text)));
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.OperationSyntaxException"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public Exception OperationSyntaxException(string text) {
|
||
|
return new Exception(Res.GetString(Res.TheOperationFromNamespaceHadInvalidSyntax3,
|
||
|
operation.Name,
|
||
|
operation.PortType.Name,
|
||
|
operation.PortType.ServiceDescription.TargetNamespace,
|
||
|
text));
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.OperationBindingSyntaxException"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public Exception OperationBindingSyntaxException(string text) {
|
||
|
return new Exception(Res.GetString(Res.TheOperationBindingFromNamespaceHadInvalid3, operationBinding.Name, operationBinding.Binding.ServiceDescription.TargetNamespace, text));
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.ProtocolName"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public abstract string ProtocolName { get; }
|
||
|
|
||
|
// These overridable methods have no parameters. The subclass uses properties on this
|
||
|
// base object to obtain the information. This allows us to grow the set of
|
||
|
// information passed to the methods over time w/o breaking anyone. They are protected
|
||
|
// instead of public because this object is passed to extensions and we don't want
|
||
|
// those calling these methods.
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.BeginNamespace"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
protected virtual void BeginNamespace() {
|
||
|
MethodNames.Clear();
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.IsBindingSupported"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
protected abstract bool IsBindingSupported();
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.IsOperationFlowSupported"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
protected abstract bool IsOperationFlowSupported(OperationFlow flow);
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.BeginClass"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
protected abstract CodeTypeDeclaration BeginClass();
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.GenerateMethod"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
protected abstract CodeMemberMethod GenerateMethod();
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.EndClass"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
protected virtual void EndClass() { }
|
||
|
/// <include file='doc\ProtocolImporter.uex' path='docs/doc[@for="ProtocolImporter.EndNamespace"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
protected virtual void EndNamespace() {
|
||
|
if (classes != null) {
|
||
|
foreach (CodeTypeDeclaration declaration in classes) {
|
||
|
codeNamespace.Types.Add(declaration);
|
||
|
}
|
||
|
}
|
||
|
CodeGenerator.ValidateIdentifiers(codeNamespace);
|
||
|
}
|
||
|
|
||
|
internal static string UniqueName(string baseName, string[] scope) {
|
||
|
CodeIdentifiers identifiers = new CodeIdentifiers();
|
||
|
for (int i = 0; i < scope.Length; i++) {
|
||
|
identifiers.AddUnique(scope[i], scope[i]);
|
||
|
}
|
||
|
return identifiers.AddUnique(baseName, baseName);
|
||
|
}
|
||
|
internal static string MethodSignature(string methodName, string returnType, CodeFlags[] parameterFlags, string[] parameterTypes) {
|
||
|
Debug.Assert(parameterFlags.Length == parameterTypes.Length, "parameterFlags.Length != parameterTypes.Length");
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
sb.Append(returnType);
|
||
|
sb.Append(" ");
|
||
|
sb.Append(methodName);
|
||
|
sb.Append(" (");
|
||
|
for (int i = 0; i < parameterTypes.Length; i++) {
|
||
|
if ((parameterFlags[i] & CodeFlags.IsByRef) != 0)
|
||
|
sb.Append("ref ");
|
||
|
else if ((parameterFlags[i] & CodeFlags.IsOut) != 0)
|
||
|
sb.Append("out ");
|
||
|
|
||
|
sb.Append(parameterTypes[i]);
|
||
|
if (i > 0)
|
||
|
sb.Append(",");
|
||
|
}
|
||
|
sb.Append(")");
|
||
|
return sb.ToString();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class ProtocolImporterUtil {
|
||
|
private ProtocolImporterUtil() { }
|
||
|
|
||
|
internal static void GenerateConstructorStatements(CodeConstructor ctor, string url, string appSettingUrlKey, string appSettingBaseUrl, bool soap11) {
|
||
|
CodeExpression value;
|
||
|
bool generateFixedUrlAssignment = (url != null && url.Length > 0);
|
||
|
bool generateConfigUrlAssignment = appSettingUrlKey != null && appSettingUrlKey.Length > 0;
|
||
|
CodeAssignStatement assignUrlStatement = null;
|
||
|
|
||
|
if (!generateFixedUrlAssignment && !generateConfigUrlAssignment)
|
||
|
return;
|
||
|
|
||
|
// this.Url property
|
||
|
CodePropertyReferenceExpression urlPropertyReference = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Url");
|
||
|
|
||
|
if (generateFixedUrlAssignment) {
|
||
|
value = new CodePrimitiveExpression(url);
|
||
|
assignUrlStatement = new CodeAssignStatement(urlPropertyReference, value);
|
||
|
}
|
||
|
|
||
|
if (generateFixedUrlAssignment && !generateConfigUrlAssignment) {
|
||
|
ctor.Statements.Add(assignUrlStatement);
|
||
|
}
|
||
|
else if (generateConfigUrlAssignment) {
|
||
|
// urlSetting local variable
|
||
|
CodeVariableReferenceExpression urlSettingReference = new CodeVariableReferenceExpression("urlSetting");
|
||
|
|
||
|
// Generate: string urlSetting = System.Configuration.ConfigurationManager.AppSettings["<appSettingUrlKey>"];
|
||
|
CodeTypeReferenceExpression codeTypeReference = new CodeTypeReferenceExpression(typeof(ConfigurationManager));
|
||
|
CodePropertyReferenceExpression propertyReference = new CodePropertyReferenceExpression(codeTypeReference, "AppSettings");
|
||
|
value = new CodeIndexerExpression(propertyReference, new CodeExpression[] { new CodePrimitiveExpression(appSettingUrlKey) });
|
||
|
ctor.Statements.Add(new CodeVariableDeclarationStatement(typeof(string), "urlSetting", value));
|
||
|
|
||
|
if (appSettingBaseUrl == null || appSettingBaseUrl.Length == 0) {
|
||
|
// Generate: this.Url = urlSetting;
|
||
|
value = urlSettingReference;
|
||
|
}
|
||
|
else {
|
||
|
// Generate: this.Url = "http://localhost/mywebapplication/simple.asmx";
|
||
|
if (url == null || url.Length == 0)
|
||
|
throw new ArgumentException(Res.GetString(Res.IfAppSettingBaseUrlArgumentIsSpecifiedThen0));
|
||
|
string relativeUrl = new Uri(appSettingBaseUrl).MakeRelative(new Uri(url));
|
||
|
CodeExpression[] parameters = new CodeExpression[] { urlSettingReference, new CodePrimitiveExpression(relativeUrl) };
|
||
|
value = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(System.String)), "Concat", parameters);
|
||
|
}
|
||
|
CodeStatement[] trueStatements = new CodeStatement[] { new CodeAssignStatement(urlPropertyReference, value) };
|
||
|
|
||
|
// Generate: if (urlSetting != null) { <truestatement> } else { <falsestatement> }
|
||
|
CodeBinaryOperatorExpression checkIfNull = new CodeBinaryOperatorExpression(urlSettingReference, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null));
|
||
|
if (generateFixedUrlAssignment)
|
||
|
ctor.Statements.Add(new CodeConditionStatement(checkIfNull, trueStatements, new CodeStatement[] { assignUrlStatement }));
|
||
|
else
|
||
|
ctor.Statements.Add(new CodeConditionStatement(checkIfNull, trueStatements));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class DelegateInfo {
|
||
|
internal string handlerType;
|
||
|
internal string handlerArgs;
|
||
|
|
||
|
internal DelegateInfo(string handlerType, string handlerArgs) {
|
||
|
this.handlerType = handlerType;
|
||
|
this.handlerArgs = handlerArgs;
|
||
|
}
|
||
|
}
|
||
|
}
|