C# 如何为没有SVC文件的自托管WCF服务指定ServiceHostFactory

C# 如何为没有SVC文件的自托管WCF服务指定ServiceHostFactory,c#,wcf,self-hosting,servicehost,was,C#,Wcf,Self Hosting,Servicehost,Was,我的应用程序作为Windows服务运行。它使用以下帮助器方法动态创建WCF服务: public static void StartWebService(string webServiceName, Type serviceContractType, Type serviceImplementationType) { if (string.IsNullOrEmpty(webServiceName)) return; var baseAddress

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

    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激活服务)下运行的

现在我想控制如何实例化实现类。听起来这是可以做到的。然而,我发现的所有关于这一点的文章都说,指定要使用的工厂的方法是将类型名放在.SVC文件的@ServiceHost指令中。我没有这个文件

有没有办法在WAS下运行没有SVC文件的WCF服务中使用我自己的ServiceHost工厂

更新以下答案

这是我结合卡洛斯解的新助手方法

    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)
    {
    }
}
public static void StartWebService(字符串webServiceName,类型serviceContractType,类型serviceImplementationType)
{
if(string.IsNullOrEmpty(webServiceName))返回;
var baseAddress=GetWebServiceAddress(webServiceName);
var baseUri=新的Uri(baseAddress);
锁定(运行Web服务)
{
if(运行webservices.ContainsKey(webServiceName))
返回;
var webServiceHost=新的ServiceHost(serviceImplementationType,baseUri);
webServiceHost.Description.Behaviors.Add(新ServiceMetadataBehavior(){HttpGetEnabled=true});
添加(新的CustomWebServiceBehavior());
webServiceHost.AddServiceEndpoint(typeof(imeadataexchange),MetadataExchangeBindings.CreateMexHttpBinding(),“mex”);
AddServiceEndpoint(serviceContractType,新的BasicHttpBinding(),baseAddress);
webServiceHost.Open();
添加(webServiceName,webServiceHost);
}
}
内部类CustomWebServiceBehavior:iInstallanceProvider的IServiceBehavior
{
public void AddBindingParameters(ServiceDescription ServiceDescription、ServiceHostBase ServiceHostBase、集合终结点、BindingParameterCollection bindingParameters)
{
}
公共无效ApplyDispatchBehavior(ServiceDescription ServiceDescription,ServiceHostBase serviceHost)
{
foreach(serviceHost.ChannelDispatchers中的ChannelDispatcher cd)
{
foreach(在cd.Endpoints中终结)
{
ed.DispatchRuntime.InstanceProvider=此;
}
}
}
公共无效验证(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
}
公共对象GetInstance(InstanceContext InstanceContext,消息)
{
返回此.GetInstance(instanceContext);
}
公共对象GetInstance(InstanceContext InstanceContext)
{
return//这是我使用工厂的地方;
}
public void ReleaseInstance(InstanceContext InstanceContext,对象实例)
{
}
}

您不需要服务主机工厂来控制服务实现类的实例化方式-您需要的是通过使用自定义服务行为向分派运行时添加一个
IInstanceProvider
。在的博客文章中有很多关于如何实现这一目标的详细信息。例如,下面显示了如何使用实例提供程序的示例(对于没有默认构造函数的服务,因此在WCF中没有实例提供程序时无法直接使用)

公共类堆栈溢出\u 29825519
{
[服务合同]
公共接口测试
{
[经营合同]
字符串WhoAmI();
}
公共类服务:ITest
{
字符串名;
公共服务(字符串名称)
{
this.name=名称;
}
公共字符串WhoAmI()
{
返回此.name;
}
}
类MyBehavior:iInstalleProvider的IServiceBehavior
{
public void AddBindingParameters(ServiceDescription ServiceDescription、ServiceHostBase ServiceHostBase、集合终结点、BindingParameterCollection bindingParameters)
{
}
公共无效ApplyDispatchBehavior(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
foreach(serviceHostBase.ChannelDispatchers中的ChannelDispatcher cd)
{
foreach(在cd.Endpoints中终结)
{
ed.DispatchRuntime.InstanceProvider=此;
}
}
}
公共无效验证(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
}
公共对象GetInstance(InstanceContext InstanceContext,消息)
{
返回此.GetInstance(instanceContext);
}
公共对象GetInstance(InstanceContext InstanceContext)
{
返回新服务(“John Doe”);
}
public void ReleaseInstance(InstanceContext InstanceContext,对象实例)
{
}
}
公共静态无效测试()
{
string baseAddress=“http://“+Environment.MachineName+”:8000/服务”;
ServiceHost主机=新ServiceHost(类型(服务),新Uri(基地址));
AddServiceEndpoint(typeof(ITest),new BasicHttpBinding(),“”);
host.Description.Behaviors.Add(新的MyBehavior());
host.Open();
Console.WriteLine(“主机已打开”);
ChannelFactory工厂=新的ChannelFactory(新的BasicHttpBinding(),新的EndpointAddress(baseAddress));
ITest proxy=factory.CreateChannel();
WriteLine(“WhoAmI:{0}”,proxy.WhoAmI());
((IClientChannel)代理).Close();
工厂关闭();
控制台。写入(“按ENTER键关闭主机”);
Console.ReadLine();
host.Close();
}
}
谢谢!我读了你的
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();
    }
}