c# - 扩展 InstanceContext Initialize 方法永远不会触发

标签 c# wcf extension-methods

我已经接管了一个根据此 Dan Rigsby's article 中的建议构建的项目。

但由于某种原因,继承 IInstanceContextIntializer 的类中的 Initalize 方法永远不会像构造函数那样被触发。我需要触发 Initialize,以便可以将扩展添加到 InstanceContext。

有人经历过这种情况并有可能的解决方案或建议吗?

非常感谢

部分代码块:

[ServiceContract]
public interface IPSRestService
{
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "blockActivityTrans", ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml)]
    transAckResponseData PostBlockActivity(blockActivityData blockactivitydata);
    ...
}

[ESBAPICreation]
    public class PSRestService : IPSRestService
    {
    ...
            public transAckResponseData PostBlockActivity(blockActivityData blockactivitydata)
        {
            OutgoingWebResponseContext outResponse = WebOperationContext.Current.OutgoingResponse;
            IncomingWebRequestContext inRequest = WebOperationContext.Current.IncomingRequest;
            bool isNew;
            transAckResponseData trans = PSDB.PutBlockActivity(blockactivitydata, out isNew);

            return trans;
        }
    ...}

public class PSRestServiceFactory : ServiceHostFactoryBase
{
    public override ServiceHostBase CreateServiceHost(string service, Uri[] baseAddresses)
    {
    // The service parameter is ignored here because we know our service.
        PSRestServiceHost serviceHost = new PSRestServiceHost(typeof(PSRestService), baseAddresses);

        serviceHost.Opening += new EventHandler(serviceHost_Opening);
        serviceHost.Opened += new EventHandler(serviceHost_Opened);
        serviceHost.Closing += new EventHandler(serviceHost_Closing);
        serviceHost.Closed += new EventHandler(serviceHost_Closed);
        serviceHost.Faulted += new EventHandler(serviceHost_Faulted);
        serviceHost.UnknownMessageReceived += new EventHandler<UnknownMessageReceivedEventArgs>(serviceHost_UnknownMessageReceived);

        return serviceHost;
    }

    void serviceHost_UnknownMessageReceived(object sender, UnknownMessageReceivedEventArgs e)
    {
        Logger.Log("Unknown Message Received");
    }

    void serviceHost_Faulted(object sender, EventArgs e)
    {
        Logger.Log("service faulted");
    }

    void serviceHost_Closed(object sender, EventArgs e)
    {
        Logger.Log("service closed");
    }

    void serviceHost_Closing(object sender, EventArgs e)
    {
        Logger.Log("service closing by sender: {0}", sender.GetType().ToString());
    }

    void serviceHost_Opened(object sender, EventArgs e)
    {
        Logger.Log("service opened by sender: {0}", sender.GetType().ToString());
    }

    void serviceHost_Opening(object sender, EventArgs e)
    {
        Logger.Log("service opening by sender: {0}", sender.GetType().ToString());
    }
}

public class PSRestServiceHost : ServiceHost
{
    public PSRestServiceHost(Type t, Uri[] addresses) : base(t, addresses)
    {
        Logger.Log("PSRestServiceHost constructor");
    }
}

[DataContract]
public class PSESBAPIExtension : IExtension<InstanceContext>
{
    private ESBAPIManager _manager;

    [DataMember]
    public ESBAPIManager ESBAPIManager
    {
        get { return _manager; }
    }

    public PSESBAPIExtension(ESBAPIManager Manager)
    {
        Logger.Log("PSESBAPIExtension constructor called");
        _manager = Manager;
    }

    public void Attach(InstanceContext owner)
    {
    }

    public void Detach(InstanceContext owner)
    {
    }
}

public class PSESBAPIInitializer : IInstanceContextInitializer
{
    private static ESBAPIManager _manager = null;

    public PSESBAPIInitializer()
    {
        if (_manager == null)
        {
            _manager = new ESBAPIManager();
            Logger.Log("New instance of API manager initialized");
        }
    }

    public void Initialize(InstanceContext instanceContext, Message message)
    {
        Logger.Log("Extension added to the instance context");

        instanceContext.Extensions.Add(new PSESBAPIExtension(_manager));
    }
}

public class ESBAPICreationAttribute : Attribute, IContractBehavior
{
    public void AddBindingParameters(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint,
        BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint,
        ClientRuntime clientRuntime)
    {
    }

    public void ApplyDispatchBehavior(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint,
        DispatchRuntime dispatchRuntime)
    {
        dispatchRuntime.InstanceContextInitializers.Add(new PSESBAPIInitializer());
        Logger.Log("Instance context initializer added");
    }

    public void Validate(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint)
    {
    }
}

最佳答案

我尝试了你的确切代码,添加了一些缺失的部分9,结果很好。主要区别是我在工厂本身中定义了端点(我想你是在 web.config 上定义的)。我尝试了 self 和网络托管的情况,并且在所有情况下都添加了初始化程序。代码如下所示。与您拥有的进行比较,差异应该可以告诉您哪里出了问题。

self 托管:

public class StackOverflow_10721469
{
    public class ESBAPICreationAttribute : Attribute, IContractBehavior
    {
        public void AddBindingParameters(
            ContractDescription contractDescription,
            ServiceEndpoint endpoint,
            BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(
            ContractDescription contractDescription,
            ServiceEndpoint endpoint,
            ClientRuntime clientRuntime)
        {
        }

        public void ApplyDispatchBehavior(
            ContractDescription contractDescription,
            ServiceEndpoint endpoint,
            DispatchRuntime dispatchRuntime)
        {
            dispatchRuntime.InstanceContextInitializers.Add(new PSESBAPIInitializer());
            Logger.Log("Instance context initializer added");
        }

        public void Validate(
            ContractDescription contractDescription,
            ServiceEndpoint endpoint)
        {
        }
    }
    public class PSESBAPIInitializer : IInstanceContextInitializer
    {
        private static ESBAPIManager _manager = null;

        public PSESBAPIInitializer()
        {
            if (_manager == null)
            {
                _manager = new ESBAPIManager();
                Logger.Log("New instance of API manager initialized");
            }
        }

        public void Initialize(InstanceContext instanceContext, Message message)
        {
            Logger.Log("Extension added to the instance context");

            instanceContext.Extensions.Add(new PSESBAPIExtension(_manager));
        }
    }
    [DataContract]
    public class PSESBAPIExtension : IExtension<InstanceContext>
    {
        private ESBAPIManager _manager;

        [DataMember]
        public ESBAPIManager ESBAPIManager
        {
            get { return _manager; }
        }

        public PSESBAPIExtension(ESBAPIManager Manager)
        {
            Logger.Log("PSESBAPIExtension constructor called");
            _manager = Manager;
        }

        public void Attach(InstanceContext owner)
        {
        }

        public void Detach(InstanceContext owner)
        {
        }
    }
    public class ESBAPIManager { }
    public class PSRestServiceHost : ServiceHost
    {
        public PSRestServiceHost(Type t, Uri[] addresses)
            : base(t, addresses)
        {
            Logger.Log("PSRestServiceHost constructor");
        }
    }
    public class PSRestServiceFactory : ServiceHostFactoryBase
    {
        public override ServiceHostBase CreateServiceHost(string service, Uri[] baseAddresses)
        {
            // The service parameter is ignored here because we know our service. 
            PSRestServiceHost serviceHost = new PSRestServiceHost(typeof(PSRestService), baseAddresses);

            serviceHost.Opening += new EventHandler(serviceHost_Opening);
            serviceHost.Opened += new EventHandler(serviceHost_Opened);
            serviceHost.Closing += new EventHandler(serviceHost_Closing);
            serviceHost.Closed += new EventHandler(serviceHost_Closed);
            serviceHost.Faulted += new EventHandler(serviceHost_Faulted);
            serviceHost.UnknownMessageReceived += new EventHandler<UnknownMessageReceivedEventArgs>(serviceHost_UnknownMessageReceived);

            return serviceHost;
        }

        void serviceHost_UnknownMessageReceived(object sender, UnknownMessageReceivedEventArgs e)
        {
            Logger.Log("Unknown Message Received");
        }

        void serviceHost_Faulted(object sender, EventArgs e)
        {
            Logger.Log("service faulted");
        }

        void serviceHost_Closed(object sender, EventArgs e)
        {
            Logger.Log("service closed");
        }

        void serviceHost_Closing(object sender, EventArgs e)
        {
            Logger.Log("service closing by sender: {0}", sender.GetType().ToString());
        }

        void serviceHost_Opened(object sender, EventArgs e)
        {
            Logger.Log("service opened by sender: {0}", sender.GetType().ToString());
        }

        void serviceHost_Opening(object sender, EventArgs e)
        {
            Logger.Log("service opening by sender: {0}", sender.GetType().ToString());
        }
    }
    [ServiceContract]
    public interface IPSRestService
    {
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "blockActivityTrans", ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml)]
        transAckResponseData PostBlockActivity(blockActivityData blockactivitydata);
    }
    [ESBAPICreation]
    public class PSRestService : IPSRestService
    {
        public transAckResponseData PostBlockActivity(blockActivityData blockactivitydata)
        {
            return new transAckResponseData();
        }
    }
    public class blockActivityData { }
    public class transAckResponseData { }
    public class Logger
    {
        public static void Log(string text, params object[] args)
        {
            if (args != null && args.Length > 0) text = string.Format(text, args);
            Console.WriteLine(text);
        }
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHostFactoryBase factory = new PSRestServiceFactory();
        ServiceHost host = (ServiceHost)factory.CreateServiceHost("unused", new Uri[] { new Uri(baseAddress) });
        host.Open();
        Console.WriteLine("Host opened");

        WebClient c = new WebClient();
        c.Headers[HttpRequestHeader.ContentType] = "application/json";
        Console.WriteLine(c.UploadString(baseAddress + "/blockActivityTrans", "null"));

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

虚拟主机:

文件:StackOverflow_10721469.svc

<%@ ServiceHost Language="C#" Debug="true" Service="StackOverflow_10721469.PSRestService"
            CodeBehind="StackOverflow_10721469.svc.cs" 
            Factory="StackOverflow_10721469.PSRestServiceFactory" %>

文件:StackOverflow_10721469.svc.cs

namespace StackOverflow_10721469
{
    public class ESBAPICreationAttribute : Attribute, IContractBehavior
    {
        public void AddBindingParameters(
            ContractDescription contractDescription,
            ServiceEndpoint endpoint,
            BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(
            ContractDescription contractDescription,
            ServiceEndpoint endpoint,
            ClientRuntime clientRuntime)
        {
        }

        public void ApplyDispatchBehavior(
            ContractDescription contractDescription,
            ServiceEndpoint endpoint,
            DispatchRuntime dispatchRuntime)
        {
            dispatchRuntime.InstanceContextInitializers.Add(new PSESBAPIInitializer());
            Logger.Log("Instance context initializer added");
        }

        public void Validate(
            ContractDescription contractDescription,
            ServiceEndpoint endpoint)
        {
        }
    }
    public class PSESBAPIInitializer : IInstanceContextInitializer
    {
        private static ESBAPIManager _manager = null;

        public PSESBAPIInitializer()
        {
            if (_manager == null)
            {
                _manager = new ESBAPIManager();
                Logger.Log("New instance of API manager initialized");
            }
        }

        public void Initialize(InstanceContext instanceContext, Message message)
        {
            Logger.Log("Extension added to the instance context");

            instanceContext.Extensions.Add(new PSESBAPIExtension(_manager));
        }
    }
    [DataContract]
    public class PSESBAPIExtension : IExtension<InstanceContext>
    {
        private ESBAPIManager _manager;

        [DataMember]
        public ESBAPIManager ESBAPIManager
        {
            get { return _manager; }
        }

        public PSESBAPIExtension(ESBAPIManager Manager)
        {
            Logger.Log("PSESBAPIExtension constructor called");
            _manager = Manager;
        }

        public void Attach(InstanceContext owner)
        {
        }

        public void Detach(InstanceContext owner)
        {
        }
    }
    public class ESBAPIManager { }
    public class PSRestServiceHost : ServiceHost
    {
        public PSRestServiceHost(Type t, Uri[] addresses)
            : base(t, addresses)
        {
            Logger.Log("PSRestServiceHost constructor");
        }
    }
    public class PSRestServiceFactory : ServiceHostFactoryBase
    {
        public override ServiceHostBase CreateServiceHost(string service, Uri[] baseAddresses)
        {
            // The service parameter is ignored here because we know our service. 
            PSRestServiceHost serviceHost = new PSRestServiceHost(typeof(PSRestService), baseAddresses);

            var endpoint = serviceHost.AddServiceEndpoint(typeof(IPSRestService), new WebHttpBinding(), "");
            endpoint.Behaviors.Add(new WebHttpBehavior());

            serviceHost.Opening += new EventHandler(serviceHost_Opening);
            serviceHost.Opened += new EventHandler(serviceHost_Opened);
            serviceHost.Closing += new EventHandler(serviceHost_Closing);
            serviceHost.Closed += new EventHandler(serviceHost_Closed);
            serviceHost.Faulted += new EventHandler(serviceHost_Faulted);
            serviceHost.UnknownMessageReceived += new EventHandler<UnknownMessageReceivedEventArgs>(serviceHost_UnknownMessageReceived);

            return serviceHost;
        }

        void serviceHost_UnknownMessageReceived(object sender, UnknownMessageReceivedEventArgs e)
        {
            Logger.Log("Unknown Message Received");
        }

        void serviceHost_Faulted(object sender, EventArgs e)
        {
            Logger.Log("service faulted");
        }

        void serviceHost_Closed(object sender, EventArgs e)
        {
            Logger.Log("service closed");
        }

        void serviceHost_Closing(object sender, EventArgs e)
        {
            Logger.Log("service closing by sender: {0}", sender.GetType().ToString());
        }

        void serviceHost_Opened(object sender, EventArgs e)
        {
            Logger.Log("service opened by sender: {0}", sender.GetType().ToString());
        }

        void serviceHost_Opening(object sender, EventArgs e)
        {
            Logger.Log("service opening by sender: {0}", sender.GetType().ToString());
        }
    }
    [ServiceContract]
    public interface IPSRestService
    {
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "blockActivityTrans", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        transAckResponseData PostBlockActivity(blockActivityData blockactivitydata);
    }
    [ESBAPICreation]
    public class PSRestService : IPSRestService
    {
        public transAckResponseData PostBlockActivity(blockActivityData blockactivitydata)
        {
            return new transAckResponseData { Logs = Logger.GetCurrentLog() };
        }
    }
    public class blockActivityData { }
    public class transAckResponseData
    {
        public string Logs { get; set; }
    }
    public static class Logger
    {
        static StringBuilder sb = new StringBuilder();
        public static void Log(string text, params object[] args)
        {
            if (args != null && args.Length > 0) text = string.Format(text, args);
            Console.WriteLine(text);
            sb.AppendLine(text);
        }
        public static string GetCurrentLog()
        {
            string result = sb.ToString();
            sb.Clear();
            return result;
        }
    }
}

文件:TestPage.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Quick template</title>
    <script type="text/javascript" src="scripts/jquery-1.7.2.js"></script>
</head>
<body>
    <script type="text/javascript">
        function StackOverflow_10721469_Test() {
            var url = "/StackOverflow_10721469.svc/blockActivityTrans";
            $.ajax({
                type: 'POST',
                url: url,
                contentType: "application/json",
                data: "{}",
                success: function (data, textStatus, jqXHR) {
                    $("#result").text(data.Logs);
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    $("#result").text("error");
                }
            });
        }
    </script>
    <input type="button" value="StackOverflow 10721469" onclick="StackOverflow_10721469_Test();" /> <br />
    <div id='result'></div>
</body>
</html>

关于c# - 扩展 InstanceContext Initialize 方法永远不会触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10721469/

相关文章:

c# - 在 C# 中循环字典

c# - 返回可空类型值的通用方法

c# - Autofac 为新线程创建子范围未按预期工作 "Instances cannot be resolved and nested lifetimes cannot be created..."

c# - 找不到 Entity Framework 6 的兼容提供者

c# - WCF 循环引用序列化和堆栈溢出错误

c# - 绑定(bind)到 WPF 中的扩展方法

wcf - WSDL 优先方法 : How to specify different names for wsdl:port and wsdl:binding?

c# - 在 MSMQ 集成绑定(bind)中处理 NormalizePoisonException

c# - C# 2.0 中的扩展方法

swift - 无法将 MyClass 类型的值转换为 MyDelegate