gpt4 book ai didi

c# - 如何为没有 SVC 文件的自承载 WCF 服务指定 ServiceHostFactory

转载 作者:太空狗 更新时间:2023-10-30 01:34:40 25 4
gpt4 key购买 nike

我的应用程序作为 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 激活服务)下运行。

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

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

更新以下答案

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

    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 中直接使用)

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();
}
}

关于c# - 如何为没有 SVC 文件的自承载 WCF 服务指定 ServiceHostFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29825519/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com