【问题标题】:Marking a referenced library class in WCF service在 WCF 服务中标记引用的库类
【发布时间】:2012-04-29 19:27:28
【问题描述】:

这与我之前提出的问题有关:

我有一个定义事务类的 DLL。它被 WCF 服务库和客户端应用程序引用。我收到错误消息,指出无法托管服务库,因为它无法序列化 DLL 类。

这是服务代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using ServerLibrary.MarketService;
using SharedLibrary; // This is the DLL in question

namespace ServerLibrary
{
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

        [OperationContract]
        bool ProcessTransaction(SharedLibrary.Transaction transaction);
    }

    [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; }
        }
    }
}

我是否必须在此处使用 [attribute] 标头标记 Transaction 类?

[更新]

这是我尝试托管此服务时收到的错误消息:

System.Runtime.Serialization.InvalidDataContractException:类型 'SharedLibrary.Transaction' 不能被序列化。考虑标记它 具有 DataContractAttribute 属性,并标记其所有 要使用 DataMemberAttribute 属性序列化的成员。 如果类型是集合,请考虑使用 集合数据合同属性。请参阅 Microsoft .NET 框架 其他支持类型的文档。在 System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(字符串 消息,类型类型)在 System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.XsdDataContractExporter.GetSchemaTypeName(类型 类型)在 System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.ValidateDataContractType(类型 类型)在 System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreatePartInfo(MessagePartDescription 部分,OperationFormatStyle 样式, DataContractSerializerOperationBehavior serializerFactory)在 System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreateMessageInfo(DataContractFormatAttribute dataContractFormatAttribute, MessageDescription messageDescription, DataContractSerializerOperationBehavior serializerFactory)在 System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter..ctor(OperationDescription 描述,DataContractFormatAttribute dataContractFormatAttribute, DataContractSerializerOperationBehavior serializerFactory)在 System.ServiceModel.Description.DataContractSerializerOperationBehavior.GetFormatter(OperationDescription 操作, Boolean& formatRequest, Boolean& formatReply, Boolean isProxy) 在 System.ServiceModel.Description.DataContractSerializerOperationBehavior.System.ServiceModel.Description.IOperationBehavior.ApplyDispatchBehavior(OperationDescription 描述,DispatchOperation 调度)在 System.ServiceModel.Description.DispatcherBuilder.BindOperations(合同描述 合同、ClientRuntime 代理、DispatchRuntime 调度)在 System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription 描述,ServiceHostBase 服务主机)在 System.ServiceModel.ServiceHostBase.InitializeRuntime() 在 System.ServiceModel.ServiceHostBase.OnBeginOpen() 在 System.ServiceModel.ServiceHostBase.OnOpen(时间跨度超时)在 System.ServiceModel.Channels.CommunicationObject.Open(时间跨度 超时)在 System.ServiceModel.Channels.CommunicationObject.Open() 在 Microsoft.Tools.SvcHost.ServiceHostHelper.OpenService(ServiceInfo 信息)

这里要求的是包含事务的 DLL:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SharedLibrary
{
    // Transaction class to encapsulate products and checkout data
    public class Transaction
    {
            public int checkoutID;
            public DateTime time;
            public List<object> products; // Using object to avoid MarketService reference, remember to cast back!
            public double totalPrice;
            public bool complete;

            public Transaction(int ID)
            {
                checkoutID = ID;
            }

            public void Start()
            {
                products = new List<object>();
                complete = false;
            }

            public void Complete()
            {
                time = DateTime.Now;
                complete = true;
            }
        }
}

谢谢。

【问题讨论】:

  • 您使用的是什么版本的 C#/WCF?
  • 如果有帮助,我正在使用 .NET 4。
  • 可以添加SharedLibrary.Transaction的定义吗?
  • 当然,用事务更新。
  • 你可以添加一个没有任何参数的默认构造函数,看看是否有效?

标签: c# wcf dll service


【解决方案1】:

我是否必须在此处使用 [attribute] 标头标记 Transaction 类?

不,您不应该这样做,但建议这样做。见Using Data Contracts


问题是您在 List&lt;object&gt; 中传递派生对象。

您必须通过ServiceKnownType 属性告诉服务要处理什么类型的对象:

[OperationContract]
[ServiceKnownType( typeof( MarketService.XXX ) )]
bool ProcessTransaction(SharedLibrary.Transaction transaction);

【讨论】:

  • 感谢 Nicholas,但我仍然遇到同样的错误。我将 MarketService.Product 应用为 typeof() 对象列表。
  • 接下来要尝试发送一个Transaction 对象,而products 列表中没有任何项目。另外,您是否遇到任何其他错误?
  • 我无法达到实际传递对象的地步。当我尝试构建 WCF 服务库并且 Visual Studio 自动托管它时,会发生这些错误。除了无法序列化 SharedLibrary.Transaction 类之外,没有新的错误。
  • 嗯,好的。如果您完全去掉 products 字段会发生什么?
  • 我已经在 Transaction 类中注释掉了产品列表,并在库的其他地方以及在 Service 和 IService 类中对其进行了引用。我上传了错误截图:i46.tinypic.com/izysme.jpg
【解决方案2】:

您可能希望如下定义您的事务类

[DataContract]
[KnownType(typeof(MarketService.XXX))]
public class Transaction
{
}

我希望这会有所帮助。

【讨论】:

  • 我将此添加到 IService 命名空间,但错误仍然存​​在。感谢您提供帮助。
  • 您可能希望在事务类级别执行此操作。试试看。
猜你喜欢
  • 1970-01-01
  • 2015-01-14
  • 1970-01-01
  • 1970-01-01
  • 2012-09-30
  • 1970-01-01
  • 2011-08-06
  • 2014-09-17
  • 1970-01-01
相关资源
最近更新 更多