WCF单例服务错误:提供的服务类型无法作为服务加载,因为它没有默认构造函数

本文关键字:服务 因为 加载 构造函数 默认 错误 单例 类型 WCF | 更新日期: 2023-09-27 18:06:06

我有以下奇怪的WCF问题,我无法找出原因:

我正在与WCF一起工作,以确定是否将其用于我需要为类似打印机的设备实现的远程控制API。该设备由一台运行。net实现的控制器软件的windows pc机控制。正是为了这个软件,我需要实现API。

服务从控制器软件内部是自托管的,我目前正在弄清楚如何创建WCF服务的单例实例,以便我可以从控制器软件内部创建具有相应对象/类的实例。我已经使用简化版本使其工作,但奇怪的是,如果服务不包含默认(无参数)构造函数,我会收到此警告。更奇怪的是,我所做的正是例外在第二句话中告诉我的(或者至少我喜欢这样认为)。这个异常在标题为WCF Service Host的单独窗口中抛出,之后程序继续正常执行:

系统。InvalidOperationException:所提供的服务类型不能作为服务加载,因为它没有默认的(无参数的)构造函数。若要解决此问题,请向该类型添加默认构造函数,或将该类型的实例传递给主机。

在System.ServiceModel.Description.ServiceDescription

。CreateImplementation (serviceType型)

在System.ServiceModel.Description.ServiceDescription

。SetupSingleton(ServiceDescription, ServiceDescription, Object implementation, Boolean isWellKnown)

在System.ServiceModel.Description.ServiceDescription

。GetService (serviceType型)

System.ServiceModel.ServiceHost.CreateDescription (IDictionary ' 2,implementedContracts)

在System.ServiceModel.ServiceHostBase

。InitializeDescription (UriSchemeKeyedCollection baseAddresses)

在System.ServiceModel.ServiceHost . .

在Microsoft.Tools.SvcHost.ServiceHostHelper

。CreateServiceHost(Type Type, ServiceKind kind)

在Microsoft.Tools.SvcHost.ServiceHostHelper

。OpenService (ServiceInfo信息)

下面是我用来创建服务的代码。我注释了Service.cs中包含默认构造函数的注释行。有趣的是,当我包含默认构造函数(因此不会抛出错误)时,它永远不会被调用(我通过设置一个断点来确认这一点)。如果您取消注释,则不会抛出异常。

Server.cs:

public class Server
{
    private ServiceHost svh;
    private Service service;
    public Server()
    {
        service = new Service("A fixed ctor test value that the service should return.");
        svh = new ServiceHost(service);
    }
    public void Open(string ipAdress, string port)
    {
        svh.AddServiceEndpoint(
        typeof(IService),
        new NetTcpBinding(),
        "net.tcp://"+ ipAdress + ":" + port);
        svh.Open();
    }
    public void Close()
    {
        svh.Close();
    }
}

Service.cs:

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant,
                 InstanceContextMode = InstanceContextMode.Single)]
public class Service : IService
{
    private string defaultString;
    public Service(string ctorTestValue)
    {
        this.defaultString = ctorTestValue;
    }
    
    //// when this constructor is uncommented, I do not get the error
    //public Service()
    //{
    //    defaultString = "Default value from the ctor without argument.";
    //}
    public string GetDefaultString()
    {
        return defaultString;
    }
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }
    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
        if (composite == null)
        {
            throw new ArgumentNullException("composite");
        }
        if (composite.BoolValue)
        {
            composite.StringValue += "Suffix";
        }
        return composite;
    }
    public string Ping(string name)
    {
        Console.WriteLine("SERVER - Processing Ping('{0}')", name);
        return "Hello, " + name;
    }
    static Action m_Event1 = delegate { };
    static Action m_Event2 = delegate { };
    public void SubscribeEvent1()
    {
        IMyEvents subscriber = OperationContext.Current.GetCallbackChannel<IMyEvents>();
        m_Event1 += subscriber.Event1;
    }
    public void UnsubscribeEvent1()
    {
        IMyEvents subscriber = OperationContext.Current.GetCallbackChannel<IMyEvents>();
        m_Event1 -= subscriber.Event1;
    }
    public void SubscribeEvent2()
    {
        IMyEvents subscriber = OperationContext.Current.GetCallbackChannel<IMyEvents>();
        m_Event2 += subscriber.Event2;
    }
    public void UnsubscribeEvent2()
    {
        IMyEvents subscriber = OperationContext.Current.GetCallbackChannel<IMyEvents>();
        m_Event2 -= subscriber.Event2;
    }
    public static void FireEvent1()
    {
        m_Event1();
    }
    public static void FireEvent2()
    {
        m_Event2();
    }
    public static Timer Timer1;
    public static Timer Timer2;
    public void OpenSession()
    {
        Timer1 = new Timer(1000);
        Timer1.AutoReset = true;
        Timer1.Enabled = true;
        Timer1.Elapsed += OnTimer1Elapsed;
        Timer2 = new Timer(500);
        Timer2.AutoReset = true;
        Timer2.Enabled = true;
        Timer2.Elapsed += OnTimer2Elapsed;
    }
    void OnTimer1Elapsed(object sender, ElapsedEventArgs e)
    {
        FireEvent1();
    }
    void OnTimer2Elapsed(object sender, ElapsedEventArgs e)
    {
        FireEvent2();
    }
}

IServices.cs:

    public interface IMyEvents
{
    [OperationContract(IsOneWay = true)]
    void Event1();
    [OperationContract(IsOneWay = true)]
    void Event2();
}
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract(CallbackContract = typeof(IMyEvents))]
public interface IService
{
    [OperationContract]
    string GetData(int value);
    [OperationContract]
    string GetDefaultString();
    [OperationContract]
    CompositeType GetDataUsingDataContract(CompositeType composite);
    // TODO: Add your service operations here
    [OperationContract]
    string Ping(string name);
    [OperationContract]
    void SubscribeEvent1();
    [OperationContract]
    void UnsubscribeEvent1();
    [OperationContract]
    void SubscribeEvent2();
    [OperationContract]
    void UnsubscribeEvent2();
    [OperationContract]
    void OpenSession();
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
// You can add XSD files into the project. After building the project, you can directly use the data types defined there, with the namespace "WcfService.ContractType".
[DataContract]
public class CompositeType
{
    bool boolValue = true;
    string stringValue = "Hello ";
    [DataMember]
    public bool BoolValue
    {
        get { return boolValue; }
        set { boolValue = value; }
    }
    [DataMember]
    public string StringValue
    {
        get { return stringValue; }
        set { stringValue = value; }
    }
}

Main用于启动服务器:

static void Main(string[] args)
{
    // start server
    var server = new Server();
    server.Open("localhost", "6700");
    Console.WriteLine("Server started.");
    Console.ReadLine();
    server.Close();
}

WCF单例服务错误:提供的服务类型无法作为服务加载,因为它没有默认构造函数

这个问题是由WcfSvcHost运行引起的,当你在Visual Studio中调试时。据此,"WCF服务主机"枚举WCF服务项目中的服务,加载项目的配置,并为它找到的每个服务实例化一个主机。该工具通过WCF服务模板集成到Visual Studio中,并在开始调试项目时调用。"

你不需要使用WCF服务主机,因为你是自托管的,所以你可以通过包含该服务的项目的项目属性页禁用它。您应该在属性页上看到一个"WCF选项"选项卡。在此基础上,关闭"启动WCF服务主机时调试…"选项。