【问题标题】:Looking for a workaround to serializing a method or constant寻找序列化方法或常量的解决方法
【发布时间】:2023-03-09 18:04:01
【问题描述】:

显然我的教育失败了,因为我没有意识到 C# 中的方法不能被序列化。 (很高兴知道。)

我正在尝试创建一个返回我创建的简单类的 WCF 服务。问题是这个简单的类包含我想要公开的方法,而我的服务的调用者将无法访问它们(假设它们没有包含类声明的 .dll)。

public class Simple
{
    public string Message { get; set; }
    private const string _Hidden = "Underpants";

    public string Hidden
    {
        get { return _Hidden; }
    }

    public string GetHidden()
    {
        return _Hidden;
    }
}

我设置了一个 WCF 服务(我们称之为 MyService)来返回我的 Simple 类的一个实例。令我沮丧的是,我只恢复了部分课程。

public void CallService()
{
    using (var client = new MyService.Serviceclient())
    {
        Simple result = client.GetSimple();
        string message = result.Message; // this works.
        string hidden = result.Hidden;  // this doesn't.
        string fail = result.GetHidden(); // Underpants remains elusive.
    }
}

是否有任何类型的解决方法,我可以在我的类上设置一个属性或方法,任何调用我的服务的人都可以访问这些属性或方法?如何处理仅存在于服务中的类中设置的常量或其他方法?

【问题讨论】:

  • 理想情况下,您可以创建一个合同,也就是一个简单的 POCO 类,它只是公共属性并将其序列化。有一些其他方法可以根据您拥有的任何内部业务逻辑/数据填充 POCO。
  • 您的用户调用您的 WCF 来执行您的逻辑,而不是让逻辑返回以在他们的系统上执行。执行您的逻辑(在服务器上)通常会导致数据(并且只有数据)被发送回客户端,以便以它需要的任何方式进行处理。
  • 这两点都非常有效,谢谢。 @cgotberg,您让我的思想朝着正确的方向发展。非常感谢!

标签: c# wcf serialization


【解决方案1】:

通常您会创建三个不同的项目。

 1. Service project
 2. Client project 
 3. Data project

Data 项目仅包含数据类 - 没有应用程序代码。这些数据类中的方法和常量应该独立于服务/客户端项目。 Data 项目作为参考包含在 Service 和 Client 项目中,因此序列化和反序列化针对同一个二进制文件进行 - 您可以保留常量/方法/等。

这里的缺点是您的所有客户端要么必须是 .NET 应用程序,要么您必须为希望支持的每个平台提供不同的数据库。

【讨论】:

    【解决方案2】:

    据我所知,WCF 服务中唯一可以返回的东西是基元或具有公共属性的类,这些公共属性上有一个 get 方法。从较高级别来看,WCF 存在允许您指定客户端和服务器之间的合同,该合同在理论上与传输无关(即,您可以将 HTTP 端点换成 netTcp 端点,并且服务将以合同级别的相同方式运行)。

    接下来要回答的问题是您试图在此服务调用中传回哪些数据。如果它是一个名为 simple 的对象,具有 Message 和 Hidden 的数据点,那么我建议创建一个名为 Simple 的数据类,将这些值作为属性:

    [DataContract]
    public class Simple
    {
        [DataMember]
        public string Hidden { get; set; }
    
        [DataMember]
        public string Message { get; set; }
    }
    

    当客户端收到回复时,Message 和 Hidden 将填充您在服务器端设置的任何值。

    DataMember 属性只能用于属性和字段。这意味着 WCF 响应只能序列化这些类型。

    如果您真的只想在 WCF 合同中使用 const,您可以将其转换为字段并在其上放置 DataMember 属性:

    public class Simple
    {
        [DataMember]
        public string Message { get; set; }
    
        [DataMember]
        public const string Hidden = "Underpants";
    }
    

    为了能够做到这一点,该字段必须是可访问的(公共的)。

    【讨论】:

    • 我的主要问题是我没有花时间创建一个只包含数据而不包含逻辑的合约类。这种方法比我的方向更有意义。谢谢!
    • 当谈到面向对象编程时,这是正确的直觉。应用程序之间的边界(在这种情况下是客户端和服务器)是一种不同的情况,如本文所述:blog.ploeh.dk/2011/05/31/…
    【解决方案3】:

    DataMember attribute 添加到您的资源中。为此,您必须同时定义 getset

    [DataMember]
    public string Hidden
    {
        get { return _Hidden; }
        set { }
    }
    

    【讨论】:

    • 很奇怪。在我的例子中,只要我添加了空集 { },它就可以访问,即使没有指定 DataMember 属性。我不确定为什么会这样,但谢谢!
    • 我认为如果你不使用DataContractAttribute标记班级,DataMemberAttribute是不必要的。你应该用DataContractAttribute 标记它以表明它是可序列化的,但正如你所见,它可以双向工作。
    【解决方案4】:

    技术上你可以做到

    public class thingToSerialize{
        public Func<ArgType1,ArgType2...,ReturnType> myFunction{get;set;}
    }
    

    然后为其分配一个接受参数并返回返回类型的 lambda 序列化之前

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-17
      • 2016-06-15
      • 2013-09-04
      • 2015-04-22
      • 1970-01-01
      • 1970-01-01
      • 2015-10-26
      • 1970-01-01
      相关资源
      最近更新 更多