通过纯代码方式发布WCF服务

Posted HOT SUMMER

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过纯代码方式发布WCF服务相关的知识,希望对你有一定的参考价值。

      网络上搜索WCF服务,一般是寄宿在IIS,通过WebConfig方式配服务地址,接口类型等信息,但是对于我这样的懒人,目前项目在开发阶段,实在不愿意每次添加新服务就更新配置文件,于是使用了反射来加载服务接口,并用控制台程序发布服务,贴上代码如下。

     

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Configuration;
using Nebula.Proxy;
using System.Reflection;
using System.Configuration;
using System.Xml;
namespace MES_WCFService
{
    public class HostIniter
    {
        public HostIniter()
        {

        }
        private ServiceHostCollection hosts;

        private Type[] interfaceTypes;
        private Type[] implTypes;
        private string addressBase;
        private string tcpPort;
        private string httpPort;
        private string basehttpPort;
        /// <summary>
        /// 通过反射获取所有服务接口及其实现类
        /// </summary>
        private void ScanService()
        {
            interfaceTypes = Assembly.Load(ConfigurationManager.AppSettings["interfaceDLLName"]).GetTypes();
            implTypes = Assembly.Load(ConfigurationManager.AppSettings["implDLLName"]).GetTypes();

        }

        public ServiceHostCollection InitHost()
        {
            
            hosts = new ServiceHostCollection();
            addressBase = ConfigurationManager.AppSettings["baseAddress"];
            tcpPort = ConfigurationManager.AppSettings["tcpPort"];
            httpPort = ConfigurationManager.AppSettings["httpPort"];
            basehttpPort = ConfigurationManager.AppSettings["basehttpPort"];
            ScanService();
            foreach (Type implType in implTypes)
            {
                try
                {

                    if (!typeof(IWCFService).IsAssignableFrom(implType))
                    {
                        continue;
                    }
                    string baseNameSpace= "http://" + addressBase + ":" + httpPort + "/WCFService/";
                    string address = baseNameSpace + implType.Name;
                    Uri baseAddress = new Uri(address);
                    ServiceHost host = new ServiceHost(implType, baseAddress);  //
                    Console.WriteLine("Add:" + implType.FullName);
                    Console.WriteLine("Address:" + address);
                    host.Description.Namespace = baseNameSpace;
                    host.Description.Name = implType.Name;
                    
                    

                    ServiceSecurityAuditBehavior secBehacior = new ServiceSecurityAuditBehavior();



                    secBehacior.MessageAuthenticationAuditLevel = AuditLevel.None;
                    secBehacior.ServiceAuthorizationAuditLevel = AuditLevel.None;

                    host.Description.Behaviors.Add(secBehacior);
                      
                    //   secBehacior.   



                    ServiceMetadataBehavior metaBehavior = new ServiceMetadataBehavior();
                    metaBehavior.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                    metaBehavior.HttpGetEnabled = true;
                    
              
                    ServiceDebugBehavior debugBehavior = host.Description.Behaviors[typeof(ServiceDebugBehavior)] as ServiceDebugBehavior;
                    debugBehavior.IncludeExceptionDetailInFaults = true;
                 

                    host.Description.Behaviors.Add(metaBehavior);

                    Type t = host.GetType();
                    object obj = t.Assembly.CreateInstance("System.ServiceModel.Dispatcher.DataContractSerializerServiceBehavior", true,
                    BindingFlags.CreateInstance | BindingFlags.Instance |
                    BindingFlags.NonPublic, null, new object[] { false, Int32.MaxValue },
                    null, null);
                    IServiceBehavior myServiceBehavior = obj as IServiceBehavior;
                    if (myServiceBehavior != null)
                    {
                        host.Description.Behaviors.Add(myServiceBehavior);
                        //  Console.WriteLine("Add DataContractSerializerServiceBehavior !");
                    }


                    ////host.Description.Behaviors.Add(debugBehavior);
                    foreach (Type interfaceType in interfaceTypes)
                    {
                        if (interfaceType == typeof(IWCFService))
                        {
                            continue;
                        }

                        if (interfaceType.IsAssignableFrom(implType))
                        {
                            //本来是WSHttpBinding 为了让Java能调用到这些服务,遂改BasicHttpBinding
                            
                            BasicHttpBinding wsBinding = new BasicHttpBinding();
                            wsBinding.Security.Mode =BasicHttpSecurityMode.None;
                            wsBinding.MaxBufferPoolSize = 524288;
                            wsBinding.MaxReceivedMessageSize = int.MaxValue;
                            
                            wsBinding.ReaderQuotas.MaxStringContentLength = 0xfffffff;
                            wsBinding.ReaderQuotas.MaxArrayLength = 0xfffffff;
                            wsBinding.ReaderQuotas.MaxBytesPerRead = 0xfffffff;
                            wsBinding.ReaderQuotas.MaxDepth = 0xfffffff;
                            wsBinding.MessageEncoding = WSMessageEncoding.Text;
                            wsBinding.TextEncoding = Encoding.UTF8;
                            wsBinding.OpenTimeout = new TimeSpan(0, 30, 0);
                            wsBinding.ReceiveTimeout = new TimeSpan(0, 30, 0);
                            wsBinding.SendTimeout = new TimeSpan(0, 30, 0);
                           
                            ContractDescription contractDescription = ContractDescription.GetContract(interfaceType);
                            ServiceEndpoint httpEndpoint = new ServiceEndpoint(contractDescription, wsBinding, new EndpointAddress(baseAddress));
                            httpEndpoint.Name = "http" + implType.Name;
                            host.Description.Endpoints.Add(httpEndpoint);

                            NetTcpBinding netTcpBinding = new NetTcpBinding() { Security = new NetTcpSecurity { Mode = SecurityMode.None } };
                            netTcpBinding.Security.Mode = SecurityMode.None;
                            netTcpBinding.MaxBufferPoolSize = 524288;
                            netTcpBinding.MaxReceivedMessageSize = int.MaxValue;
                            netTcpBinding.ReaderQuotas.MaxStringContentLength = 0xfffffff;
                            netTcpBinding.ReaderQuotas.MaxArrayLength = 0xfffffff;
                            netTcpBinding.ReaderQuotas.MaxBytesPerRead = 0xfffffff;
                            netTcpBinding.ReaderQuotas.MaxDepth = 0xfffffff;
                            netTcpBinding.OpenTimeout = new TimeSpan(0, 30, 0);
                            netTcpBinding.ReceiveTimeout = new TimeSpan(0, 30, 0);
                            netTcpBinding.SendTimeout = new TimeSpan(0, 30, 0);
                            ServiceEndpoint tcpEndpoint = new ServiceEndpoint(contractDescription, netTcpBinding, new EndpointAddress("net.tcp://" + addressBase + ":" + tcpPort + "/WCFService/" + implType.Name));
                            tcpEndpoint.Name = "tcp" + implType.Name;
                            host.Description.Endpoints.Add(tcpEndpoint);





                            host.AddServiceEndpoint(
                                ServiceMetadataBehavior.MexContractName,
                                MetadataExchangeBindings.CreateMexHttpBinding(),
                                "mex"
                            );

                            break;
                        }
                    }
                    //添加自定义的 Behavior
                    host.Description.Behaviors.Add(new MesServiceInterceptorAttribute());


                    hosts.Add(host);
                }


                catch (Exception commProblem)
                {

                    Console.WriteLine("There was a  problem with this type ;"+implType.FullName);
                    Console.WriteLine("Message:" + commProblem.Message);
                    Console.WriteLine("StackTrace:" + commProblem.StackTrace);
                    Console.Read();
                }

            }
            return hosts;
        }

    }
}
MesServiceInterceptorAttribute的代码

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

namespace MES_WCFService
{
    [AttributeUsage(AttributeTargets.Class)]
    public class MesServiceInterceptorAttribute : Attribute, IServiceBehavior
    {
        protected MesOperationInterceptorAttribute CreateOperationInterceptor()
        {
            return new MesOperationInterceptorAttribute();
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase host)
        {
            foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
            {
                foreach (OperationDescription operation in endpoint.Contract.Operations)
                {
                    bool checkresult = false;
                    foreach (IOperationBehavior behavior in operation.Behaviors)
                    {
                        if (behavior is MesOperationInterceptorAttribute)
                        {
                            checkresult = true;
                            break;
                        }
                    }
                    if (!checkresult)
                    {
                        operation.Behaviors.Add(CreateOperationInterceptor());
                    }
                }
            }
        }
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        { }

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }
    }
}
MesOperationInterceptorAttribute的:

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

using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
namespace MES_WCFService
{
    [AttributeUsage(AttributeTargets.Method)]
    public class MesOperationInterceptorAttribute : Attribute, IOperationBehavior
    {
       //private InterceptionType m_InteType = InterceptionType.None;
        private string _operatName;
    public MesOperationInterceptorAttribute() { }

//public MesOperationInterceptorAttribute(InterceptionType inteType)
//{
//    this.m_InteType = inteType;
//}

    protected MesInvoker CreateInvoker(IOperationInvoker oldInvoker)
    {
        return new MesInvoker(oldInvoker, _operatName);
    }

    public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
    { }

    public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
    { }

    public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
    {
        IOperationInvoker oldInvoker = dispatchOperation.Invoker;
        _operatName = dispatchOperation.Name;
        dispatchOperation.Invoker = CreateInvoker(oldInvoker);
    }

    public void Validate(OperationDescription operationDescription)
    { }
    }
}

 

以上是关于通过纯代码方式发布WCF服务的主要内容,如果未能解决你的问题,请参考以下文章

通过C#代码调用WCF服务中的一个方法。不依赖配置文件等。求完整代码!!

[转]使用代码去描述WCF配置文件

如何以编程方式将客户端连接到 WCF 服务?

WCF系列教程之WCF服务配置

如果需要,如何编写调用 WCF 服务并从 Kerberos 回退到 NTLM 的代码?

WCF