为什么 InstanceContextMode.Single 不工作?

Why isn't InstanceContextMode.Single working?

我正在尝试在 InstanceContextMode.Single 中将 WCF 服务获取到 运行,这样所有请求都可以共享相同的服务状态。但是,当我尝试以这种行为启动服务时,我仍然可以看到每个请求都会调用服务的构造函数。我想不出更新 ServiceBehaviorAttribute 的快速方法,所以我要替换它(InstanceContextMode 的默认值不是 Single)。似乎在我们启动它时有一个实例,然后是针对稍后出现的所有请求的另一个实例。有什么想法可能会出错吗?

/// <summary>Constructor</summary>
CAutomation::CAutomation()
{
    //TODO:  pull from config
    m_Host = gcnew ServiceHost(CAutomation::typeid, gcnew Uri("http://localhost:8001/GettingStarted"));

    // add a service endpoint.
    m_Host->AddServiceEndpoint(IAutomation::typeid, gcnew WSHttpBinding(), "Automation");

    // add behavior
    ServiceMetadataBehavior^ smb = gcnew ServiceMetadataBehavior();
    smb->HttpGetEnabled = true;
    m_Host->Description->Behaviors->Add(smb);

    // enforce single instance behavior
    m_Host->Description->Behaviors->RemoveAt(0);
    ServiceBehaviorAttribute^ sba = gcnew ServiceBehaviorAttribute();
    sba->InstanceContextMode = InstanceContextMode::Single;
    m_Host->Description->Behaviors->Add(sba);
}

/// <summary>Starts the automation service.</summary>
void CAutomation::Start()
{
    m_Host->Open();
}

通常,您将 ServiceBehaviorAttribute 设置为实现服务的 class 的真实属性。我不是 C++/CLI 专家,但我想既然你将 CAutomation::typeid 传递给 ServiceHost 构造函数,那么 CAutomation 就是你的服务 class。对吗?

如果是这样,那么在 CAutomation class 上设置 ServiceBehaviorAttribute 就足够了。

Igor Labutin 为我指出了正确的方向,但真正的问题是服务宿主对象的创建将创建一个 class 的实例,其类型被传递给它的构造函数,至少在在 [ServiceBehaviorAttribute(InstanceContextMode = InstanceContextMode::Single)]。基本上,ServiceHost 对象不应该是 CAutomation class 构造函数。我将该对象从该构造函数移到另一个对象中,该对象负责服务何时应该启动并纠正了问题。我将粘贴一段代码示例,这有助于说明更好的方法。

class Program
{
    static void Main(string[] args)
    {
        Uri address = new Uri
            ("http://localhost:8080/QuickReturns/Exchange");
        ServiceHost host = new ServiceHost(typeof(TradeService);
        host.Open();
        Console.WriteLine("Service started: Press Return to exit");
        Console.ReadLine();
     }
 } 

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,
    ReturnUnknownExceptionsAsFaults=true)]
public class TradeService : ITradeService
{
    private Hashtable tickers = new Hashtable();
    public Quote GetQuote(string ticker)
    {
        lock (tickers)
        {
            Quote quote = tickers[ticker] as Quote;
            if (quote == null)
            {
                // Quote doesn't exist
                throw new Exception(
                    string.Format("No quotes found for ticker '{0}'",
                    ticker)); 
            }
            return quote;
        }
    }
    public void PublishQuote(Quote quote)
    {
        lock (tickers)
        {
            Quote storedQuote = tickers[quote.Ticker] as Quote;
            if (storedQuote == null)
            {
                tickers.Add(quote.Ticker, quote);
            }
            else
            {
                tickers[quote.Ticker] = quote;
            }
        }
    }
}