4

经过一番调查,我昨天注意到了这一点,但对仅仅知道这一点并不满意。有人可以向我解释一下吗?

这是我正在经历的:

  • 我看到了两种不同的序列化可能性:
    • [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    • [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
  • 涉及 Runtime.Serialization 的序列化会导致实体ArrayOf<T>被引入,如果任何集合预期作为 Web 方法的参数。
    • public void Foo(int[] ids) ==> public void Foo(int[] ids) System.ServiceModel
    • public void Foo(int[] ids) ==> public void Foo(ArrayOfInt ids) System.Runtime.Serialization
  • 选择的序列化引擎取决于派生自(或作为)抽象类类型的参数。
    • 使用public void Bar(int[] ids) ==> System.Runtime.Serialization
    • public void Bar(DerivedFromAbstractClass baz, int[] ids) ==> System.ServiceModel被使用。

作为一个可运行的例子:

public abstract class Foo { }

/// <summary>
/// Summary description for WebService1
/// </summary>
[System.Web.Services.WebService(Namespace = "http://tempuri.org/")]
[System.Web.Services.WebServiceBinding(ConformsTo = System.Web.Services.WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
// [System.Web.Script.Services.ScriptService]
public class WebService1 : System.Web.Services.WebService
{
    [System.Web.Services.WebMethod]
    public void HelloWorld(Foo foo, int[] ids)
    {
    }
}

这是我的 .asmx 文件的样子。注意 hello world 期望的参数类型。现在,我生成一个服务引用:

namespace CableSolve.Web.Api.Tests.ServiceReference1 {
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.WebService1Soap")]
    public interface WebService1Soap {

        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/HelloWorld", ReplyAction="*")]
        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
        void HelloWorld(CableSolve.Web.Api.Tests.ServiceReference1.Foo foo, int[] ids);
    }

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.233")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]
    public abstract partial class Foo : object, System.ComponentModel.INotifyPropertyChanged {

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string propertyName) {
            System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
            if ((propertyChanged != null)) {
                propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }
    }

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public interface WebService1SoapChannel : CableSolve.Web.Api.Tests.ServiceReference1.WebService1Soap, System.ServiceModel.IClientChannel {
    }

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public partial class WebService1SoapClient : System.ServiceModel.ClientBase<CableSolve.Web.Api.Tests.ServiceReference1.WebService1Soap>, CableSolve.Web.Api.Tests.ServiceReference1.WebService1Soap {

        public WebService1SoapClient() {
        }

        public WebService1SoapClient(string endpointConfigurationName) : 
                base(endpointConfigurationName) {
        }

        public WebService1SoapClient(string endpointConfigurationName, string remoteAddress) : 
                base(endpointConfigurationName, remoteAddress) {
        }

        public WebService1SoapClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(endpointConfigurationName, remoteAddress) {
        }

        public WebService1SoapClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(binding, remoteAddress) {
        }

        public void HelloWorld(CableSolve.Web.Api.Tests.ServiceReference1.Foo foo, int[] ids) {
            base.Channel.HelloWorld(foo, ids);
        }
    }
}

请注意没有 ArrayOfInt。现在,我从 WebService1 中删除 Foo 参数并生成第二个服务引用。观察:

namespace CableSolve.Web.Api.Tests.ServiceReference2 {
    using System.Runtime.Serialization;
    using System;


    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
    [System.Runtime.Serialization.CollectionDataContractAttribute(Name="ArrayOfInt", Namespace="http://tempuri.org/", ItemName="int")]
    [System.SerializableAttribute()]
    public class ArrayOfInt : System.Collections.Generic.List<int> {
    }

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference2.WebService1Soap")]
    public interface WebService1Soap {

        // CODEGEN: Generating message contract since element name ids from namespace http://tempuri.org/ is not marked nillable
        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/HelloWorld", ReplyAction="*")]
        CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldResponse HelloWorld(CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequest request);
    }

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
    [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
    public partial class HelloWorldRequest {

        [System.ServiceModel.MessageBodyMemberAttribute(Name="HelloWorld", Namespace="http://tempuri.org/", Order=0)]
        public CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequestBody Body;

        public HelloWorldRequest() {
        }

        public HelloWorldRequest(CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequestBody Body) {
            this.Body = Body;
        }
    }

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
    [System.Runtime.Serialization.DataContractAttribute(Namespace="http://tempuri.org/")]
    public partial class HelloWorldRequestBody {

        [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=0)]
        public CableSolve.Web.Api.Tests.ServiceReference2.ArrayOfInt ids;

        public HelloWorldRequestBody() {
        }

        public HelloWorldRequestBody(CableSolve.Web.Api.Tests.ServiceReference2.ArrayOfInt ids) {
            this.ids = ids;
        }
    }

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
    [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
    public partial class HelloWorldResponse {

        [System.ServiceModel.MessageBodyMemberAttribute(Name="HelloWorldResponse", Namespace="http://tempuri.org/", Order=0)]
        public CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldResponseBody Body;

        public HelloWorldResponse() {
        }

        public HelloWorldResponse(CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldResponseBody Body) {
            this.Body = Body;
        }
    }

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
    [System.Runtime.Serialization.DataContractAttribute()]
    public partial class HelloWorldResponseBody {

        public HelloWorldResponseBody() {
        }
    }

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public interface WebService1SoapChannel : CableSolve.Web.Api.Tests.ServiceReference2.WebService1Soap, System.ServiceModel.IClientChannel {
    }

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public partial class WebService1SoapClient : System.ServiceModel.ClientBase<CableSolve.Web.Api.Tests.ServiceReference2.WebService1Soap>, CableSolve.Web.Api.Tests.ServiceReference2.WebService1Soap {

        public WebService1SoapClient() {
        }

        public WebService1SoapClient(string endpointConfigurationName) : 
                base(endpointConfigurationName) {
        }

        public WebService1SoapClient(string endpointConfigurationName, string remoteAddress) : 
                base(endpointConfigurationName, remoteAddress) {
        }

        public WebService1SoapClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(endpointConfigurationName, remoteAddress) {
        }

        public WebService1SoapClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(binding, remoteAddress) {
        }

        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
        CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldResponse CableSolve.Web.Api.Tests.ServiceReference2.WebService1Soap.HelloWorld(CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequest request) {
            return base.Channel.HelloWorld(request);
        }

        public void HelloWorld(CableSolve.Web.Api.Tests.ServiceReference2.ArrayOfInt ids) {
            CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequest inValue = new CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequest();
            inValue.Body = new CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequestBody();
            inValue.Body.ids = ids;
            CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldResponse retVal = ((CableSolve.Web.Api.Tests.ServiceReference2.WebService1Soap)(this)).HelloWorld(inValue);
        }
    }
}

有没有搞错?为什么 HelloWorld 的第二个参数的类型期望取决于另一个派生自抽象类或作为抽象类的参数的存在?是否可以让 HelloWorld 只期望没有 Foo 参数的 int[] id,而不期望 ArrayOfInt?

4

0 回答 0