如何为没有SVC文件的自托管WCF服务指定ServiceHostFactory [英] How to specify ServiceHostFactory for self-hosted WCF service with no SVC file

查看:141
本文介绍了如何为没有SVC文件的自托管WCF服务指定ServiceHostFactory的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序作为Windows服务运行.它使用以下帮助程序方法动态创建WCF服务:

My application runs as a Windows service. It dynamically creates WCF services using the following helper method:

    public static void StartWebService(string webServiceName, Type serviceContractType, Type serviceImplementationType)
    {
        if (string.IsNullOrEmpty(webServiceName)) return;

        var baseAddress = GetWebServiceAddress(webServiceName);
        var baseUri = new Uri(baseAddress);

        lock (RunningWebServices)
        {
            if (RunningWebServices.ContainsKey(webServiceName))
                return;

            var webServiceHost = new ServiceHost(serviceImplementationType, baseUri);

            var serviceBehaviour = new ServiceMetadataBehavior() { HttpGetEnabled = true };
            webServiceHost.Description.Behaviors.Add(serviceBehaviour);
            webServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");

            var httpBinding = new BasicHttpBinding();
            webServiceHost.AddServiceEndpoint(serviceContractType, httpBinding, baseAddress);
            webServiceHost.Open();

            RunningWebServices.Add(webServiceName, webServiceHost);
        }
    }

没有用于这些服务的.SVC文件.还应该清楚这些是自托管服务,不在IIS下运行-它们在WAS(Windows激活服务)下运行.

There is no .SVC file for these services. Also be clear that these are self-hosted services, not running under IIS - they are running under WAS (Windows Activation Services).

现在,我想控制如何实例化实现类.听起来可以使用ServiceHostFactory 完成一个>.但是我发现的所有有关此文章的文章都指出,指定要使用的工厂的方法是将类型名称放入.SVC文件的@ServiceHost指令中.我没有这个文件!

Now I want to control how the implementation class is instantiated. It sounds like this can be done with a ServiceHostFactory. However all the articles about this I have found say that the way to specify what factory to used is to put the type name in the @ServiceHost directive of the .SVC file. I don't have this file!

有什么方法可以将我自己的ServiceHost工厂用于WCF服务,而没有在WAS下运行SVC文件吗?

Is there any way to use my own ServiceHost factory for WCF services with no SVC file running under WAS?

根据答案更新

这是我结合了Carlos解决方案的新辅助方法

Here is my new helper method incorporating Carlos' solution

    public static void StartWebService(string webServiceName, Type serviceContractType, Type serviceImplementationType)
    {
        if (string.IsNullOrEmpty(webServiceName)) return;

        var baseAddress = GetWebServiceAddress(webServiceName);
        var baseUri = new Uri(baseAddress);

        lock (RunningWebServices)
        {
            if (RunningWebServices.ContainsKey(webServiceName))
                return;

            var webServiceHost = new ServiceHost(serviceImplementationType, baseUri);

            webServiceHost.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });
            webServiceHost.Description.Behaviors.Add(new CustomWebServiceBehavior());

            webServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
            webServiceHost.AddServiceEndpoint(serviceContractType, new BasicHttpBinding(), baseAddress);

            webServiceHost.Open();

            RunningWebServices.Add(webServiceName, webServiceHost);
        }
    }

internal class CustomWebServiceBehavior : IServiceBehavior, IInstanceProvider
{
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHost)
    {
        foreach (ChannelDispatcher cd in serviceHost.ChannelDispatchers)
        {
            foreach (EndpointDispatcher ed in cd.Endpoints)
            {
                ed.DispatchRuntime.InstanceProvider = this;
            }
        }
    }

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

    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        return this.GetInstance(instanceContext);
    }

    public object GetInstance(InstanceContext instanceContext)
    {
        return // this is where I use my factory;
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
    }
}

推荐答案

您不需要服务宿主工厂来控制如何实例化服务实现类-您需要的是向调度运行时添加IInstanceProvider ,通过使用自定义服务行为. http://blogs上的博客文章.msdn.com/b/carlosfigueira/archive/2011/05/31/wcf-extensibility-iinstanceprovider.aspx 有关如何实现此目标的详细信息.例如,下面的 SSCCE 显示了如何使用实例提供程序的示例(用于没有默认设置的服务构造函数,因此在没有WCF的情况下,不能直接使用它而没有实例提供程序)

You don't need a service host factory to control how the service implementation class is instantiated - what you need is to add an IInstanceProvider to your dispatch runtime, by using a custom service behavior. The blog post at http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/31/wcf-extensibility-iinstanceprovider.aspx has a lot more details on how this can be achieved. For example, the SSCCE below shows how an example of an instance provider being used (for a service which does not have a default constructor, so it cannot be used directly, without an instance provider, in WCF)

public class StackOverflow_29825519
{
    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        string WhoAmI();
    }
    public class Service : ITest
    {
        string name;

        public Service(string name)
        {
            this.name = name;
        }

        public string WhoAmI()
        {
            return this.name;
        }
    }
    class MyBehavior : IServiceBehavior, IInstanceProvider
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
            {
                foreach (EndpointDispatcher ed in cd.Endpoints)
                {
                    ed.DispatchRuntime.InstanceProvider = this;
                }
            }
        }

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

        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            return this.GetInstance(instanceContext);
        }

        public object GetInstance(InstanceContext instanceContext)
        {
            return new Service("John Doe");
        }

        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
        }
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
        host.Description.Behaviors.Add(new MyBehavior());
        host.Open();
        Console.WriteLine("Host opened");

        ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
        ITest proxy = factory.CreateChannel();
        Console.WriteLine("WhoAmI: {0}", proxy.WhoAmI());

        ((IClientChannel)proxy).Close();
        factory.Close();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}

这篇关于如何为没有SVC文件的自托管WCF服务指定ServiceHostFactory的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆