WCF服务编程读书笔记(1,2):WCF基础 & 服务契约

例2-1:服务端的操作重载

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace WCFServiceProgramming
{
    [ServiceContract]
    class ICalculator
    {
        [OperationContract(Name = "AddInt")]
        int Add(int arg1, int arg2);

        [OperationContract(Name = "AddDouble")]
        double Add(double arg1, double arg2);
    }
}
View Code

例2-2:客户端操作重载

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace WCFServiceProgramming
{
    public partial class CalculatorClient : ClientBase<ICalculator>, ICalculator
    {
        public int Add(int arg1, int arg2)
        {
            return Channel.Add(arg1, arg2);
        }

        public double Add(double arg1, double arg2)
        {
            return Channel.Add(arg1, arg2);
        }
    }
}
View Code

例 2-3:服务端契约层级

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace WCFServiceProgramming
{
    [ServiceContract]
    interface ISimpleCalculator
    {
        [OperationContract]
        int Add(int arg1, int arg2);
    }

    [ServiceContract]
    interface IScientificCalculator : ISimpleCalculator
    {
        [OperationContract]
        int Multiply(int arg1, int arg2);
    }

    class MyCalculator : IScientificCalculator
    {
        public int Multiply(int arg1, int arg2)
        {
            return arg1 * arg2;
        }

        public int Add(int arg1, int arg2)
        {
            return arg1 + arg2;
        }
    }
}
View Code

例2-4:取消层级关系的客户端定义

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace WCFServiceProgramming
{
    [ServiceContract]
    public interface IScientificCalculator 
    {
        [OperationContract(Action=".../ISimpleCalculator/Add", 
            ReplyAction=".../ISimpleCalculator/AddResponse")]
        int Add(int arg1, int arg2);

        [OperationContract(Action=".../IScientificCalculator/Multiply", 
            ReplyAction=".../IScientificCalculator/MultiplyResponse")]
        int Multiply(int arg1, int arg2);
    }

    public partial class ScientificCalculatorClient : 
        ClientBase<IScientificCalculator>, IScientificCalculator
    {
        public int Add(int arg1, int arg2)
        {
            return arg1 + arg2;
        }

        public int Multiply(int arg1, int arg2)
        {
            return arg1 * arg2;
        }
    }
}
View Code

例2-5:客户端契约层级

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace WCFServiceProgramming
{
    [ServiceContract]
    public interface ISimpleCalculator
    {
        [OperationContract]
        int Add(int arg1, int arg2);
    }

    public partial class SimpleCalculatorClient : 
        ClientBase<ISimpleCalculator>, ISimpleCalculator
    {
        public int Add(int arg1, int arg2)
        {
            return Channel.Add(arg1, arg2);
        }
    }

    [ServiceContract]
    public interface IScientificCalculator : ISimpleCalculator
    {
        [OperationContract]
        int Multiply(int arg1, int arg2);
    }

    public partial class ScientificCalculatorClient : 
        ClientBase<IScientificCalculator>, IScientificCalculator
    {
        public int Add(int arg1, int arg2)
        {
            return Channel.Add(arg1, arg2);
        }

        public int Multiply(int arg1, int arg2)
        {
            return Channel.Multiply(arg1, arg2);
        }
    }
}
View Code

例2-6:代理链

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace WCFServiceProgramming
{
    [ServiceContract]
    public interface ISimpleCalculator
    {
        [OperationContract]
        int Add(int arg1, int arg2);
    }

    [ServiceContract]
    public interface IScientificCalculator : ISimpleCalculator
    {
        [OperationContract]
        int Multiply(int arg1, int arg2);
    }

    public partial class SimpleCalculatorClient :
        ClientBase<IScientificCalculator>, ISimpleCalculator
    {
        public int Add(int arg1, int arg2)
        {
            return Channel.Add(arg1, arg2);
        }
    }

    public partial class ScientificCalculatorClient : 
        SimpleCalculatorClient, IScientificCalculator
    {
        public int Multiply(int arg1, int arg2)
        {
            return Channel.Multiply(arg1, arg2);
        }
    }
}
View Code

例2-7:支持元数据处理的类型

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime;
using System.Xml;
using System.Xml.Serialization;
using System.Net;
using System.Net.Mime;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;

namespace System.ServiceModel.Description
{
    public enum MetadataExchangeClientMode
    {
        MetadataExchange = 0,
        HttpGet = 1,
    }

    public class MetadataSet : IXmlSerializable
    {
    }

    public class ServiceEndpointCollection : Collection<ServiceEndpoint>
    {
    }

    public class MetadataExchangeClient
    {
        public MetadataExchangeClient();
        public MetadataExchangeClient(Binding mexBinding);
        public MetadataExchangeClient(Uri address, MetadataExchangeClientMode mode);

        public MetadataSet GetMetadata();
        public MetadataSet GetMetadata(EndpointAddress address);
    }

    public abstract class MetadataImporter
    {
        public abstract ServiceEndpointCollection ImportAllEndpoints();
    }

    public class WsdlImporter : MetadataImporter
    {
        public WsdlImporter(MetadataSet metadata);
    }

    public class ServiceEndpoint
    {
        public EndpointAddress Address { get; set; }
        public Binding Binding { get; set; }
        public ContractDescription Contract { get; set; }
    }

    public class ContractDescription
    {
        public string Name { get; set; }
        public string Namespace { get; set; }
    }
}
View Code

例2-8:查询契约的地址

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;

namespace WCFServiceProgramming
{
    class Program
    {
        static void Main(string[] args)
        {
            bool contractSupported = false;
            string mexAddress = "...?WSDL";

            MetadataExchangeClient mexClient = new MetadataExchangeClient(
                new Uri(mexAddress), MetadataExchangeClientMode.HttpGet);

            MetadataSet metadata = mexClient.GetMetadata();
            MetadataImporter importer = new WsdlImporter(metadata);

            ServiceEndpointCollection endpoints = importer.ImportAllEndpoints();

            foreach (ServiceEndpoint endpoint in endpoints)
            {
                if (endpoint.Contract.Namespace == "MyNamespace" && 
                    endpoint.Contract.Name == "IMyContract")
                {
                    contractSupported = true;
                    break;
                }
            }
        }
    }
}
View Code

例 2-9 MetadataHelper.QueryContract() 的实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Diagnostics;

namespace WCFServiceProgramming
{
    public static class MetadataHelper
    {
        const int MessageMultiplier = 5;

        static ServiceEndpointCollection QueryMexEndpoint(string mexAddress, 
            BindingElement bindingElement)
        {
            CustomBinding binding = new CustomBinding(bindingElement);

            MetadataExchangeClient MEXClient = new MetadataExchangeClient(binding);
            MetadataSet metadata = MEXClient.GetMetadata(new EndpointAddress(mexAddress));

            MetadataImporter importer = new WsdlImporter(metadata);
            return importer.ImportAllEndpoints();
        }

        public static ServiceEndpoint[] GetEndpoints(string mexAddress)
        {
            Uri address = new Uri(mexAddress);
            ServiceEndpointCollection endpoints = null;

            if(address.Scheme == "net.tcp")
            {
                TcpTransportBindingElement tcpBindingElement = new TcpTransportBindingElement();

                tcpBindingElement.MaxReceivedMessageSize *= MessageMultiplier;
                endpoints = QueryMexEndpoint(mexAddress,tcpBindingElement);
            }

            if (address.Scheme == "net.pipe") { }
            if (address.Scheme == "http") { }
            if (address.Scheme == "https") { }

            return endpoints.ToArray();
        }

        public static bool QueryContract(string mexAddress, Type contractType)
        {
            if (contractType.IsInterface == false)
            {
                Debug.Assert(false, contractType + " is not an interface");
                return false;
            }

            object[] attributes = contractType.GetCustomAttributes(
                typeof(ServiceContractAttribute), false);

            if (attributes.Length == 0)
            {
                Debug.Assert(false, "Interface " + contractType + " does not have the ServiceContractAttribute");
                return false;
            }

            ServiceContractAttribute attribute = attributes[0] as ServiceContractAttribute;

            if (attribute.Name == null)
            {
                attribute.Name = contractType.ToString();
            }

            if (attribute.Namespace == null)
            {
                attribute.Namespace = "http://tempuri.org/";
            }

            return QueryContract(mexAddress, attribute.Namespace, attribute.Name);
        }

        private static bool QueryContract(string mexAddress, string contractNamespace, string contractName)
        {
            if (String.IsNullOrEmpty(contractNamespace))
            {
                Debug.Assert(false, "Empty namespace");
                return false;
            }

            if (String.IsNullOrEmpty(contractName))
            {
                Debug.Assert(false, "Empty name");
                return false;
            }

            try
            {
                ServiceEndpoint[] endpoints = GetEndpoints(mexAddress);

                foreach (ServiceEndpoint endpoint in endpoints)
                {
                    if (endpoint.Contract.Namespace == contractNamespace
                        && endpoint.Contract.Name == contractName)
                    {
                        return true;
                    }
                }
            }
            catch { }

            return false;
        }
    }
}
View Code

例 2-10 MetadataHelper类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Diagnostics;

namespace WCFServiceProgramming
{
    public static class MetadataHelper
    {
        public static ServiceEndpoint[] GetEndpoints(string mexAddress);

        public static string[] GetAddresses(string mexAddress, Type contractType);
        public static string[] GetAddresses(string mexAddress, string contractNamespace, string contractName);
        public static string[] GetAddresses(Type bindingType, string mexAddress, Type contractType);
        public static string[] GetAddresses(Type bindingType, 
            string mexAddress, string contractNamespace, string contractName);

        public static string[] GetContracts(string mexAddress);
        public static string[] GetContracts(Type bindingType, string mexAddress);

        public static string[] GetOperations(string mexAddress, Type contractType);
        public static string[] GetOperations(string mexAddress, string contractNamespace, string contractName);

        public static bool QueryContract(string mexAddress, Type contractType);
        public static bool QueryContract(string mexAddress, string contractNamespace, string contractName);
    }
}
View Code
原文地址:https://www.cnblogs.com/thlzhf/p/2783011.html