Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net WCF:公开不带集合的只读DataMember属性?_.net_Wcf_Readonly_Datacontract_Datamember - Fatal编程技术网

.net WCF:公开不带集合的只读DataMember属性?

.net WCF:公开不带集合的只读DataMember属性?,.net,wcf,readonly,datacontract,datamember,.net,Wcf,Readonly,Datacontract,Datamember,我有一个服务器端类,可以通过[DataContract]在客户端使用它。这个类有一个只读字段,我想通过属性使其可用。但是,我无法这样做,因为似乎不允许我在没有get和set的情况下添加[DataMember]属性 那么-有没有一种不使用setter就拥有[DataMember]属性的方法 [DataContract] class SomeClass { private readonly int _id; public SomeClass() { .. } [Data

我有一个服务器端类,可以通过[DataContract]在客户端使用它。这个类有一个只读字段,我想通过属性使其可用。但是,我无法这样做,因为似乎不允许我在没有get和set的情况下添加[DataMember]属性

那么-有没有一种不使用setter就拥有[DataMember]属性的方法

[DataContract]
class SomeClass
{
    private readonly int _id; 

    public SomeClass() { .. }

    [DataMember]
    public int Id { get { return _id; } }        

    [DataMember]
    public string SomeString { get; set; }
}
或者该解决方案将使用[DataMember]作为字段-(如图所示)?也尝试过这样做,但似乎不关心字段是否为只读

编辑:这是通过这样的黑客攻击来创建只读属性的唯一方法吗?(不-我不想这样做…)


在使用类实现契约之前定义服务契约(接口)。

将DataMember属性放在字段而不是属性上

记住,WCF不知道封装。封装是一个OOP术语,而不是SOA术语

也就是说,请记住,该字段对于使用您的类的人是只读的-任何使用该服务的人都可以完全访问该字段。

您的“服务器端”类实际上不会“提供给”客户端

发生的情况是:基于数据契约,客户机将从服务的XML模式中创建一个新的独立类。它本身不能使用服务器端类

它将根据XML模式定义重新创建一个新类,但该模式不包含任何特定于.NET的内容,如可见性或访问修饰符—毕竟,它只是一个XML模式。客户端类的创建方式将使其在线路上具有相同的“封装外形”——例如,它基本上序列化为相同的XML格式

无法通过标准的基于SOAP的服务“传输”.NET特定的类专有技术-毕竟,您传递的都是序列化消息-没有类

勾选“SOA的四个原则”(由微软的Don Box定义):

  • 边界是明确的
  • 服务是自主的
  • 服务共享架构和契约,而不是类
  • 兼容性基于策略

  • 请参阅第3点-服务共享模式和契约,而不是类-您只共享数据契约的接口和XML模式-仅此而已-没有.NET类。

    我想将服务层中的类中的一些属性传递给Silverlight。我不想创建一个全新的类

    不是真正的“推荐”,但这似乎是将
    Total
    属性传递给silverlight(仅用于可视化数据绑定)的两个缺点中较小的一个


    有一种方法可以实现这一点。但请注意,它直接违反了本节中引用的以下原则:

    3.服务共享架构和协定,而不是类

    如果这一违规行为与您无关,您可以这样做:

  • 将服务和数据契约移动到单独的(可移植的)类库中。(我们将此程序集称为
    SomeService.Contracts
    )这是定义不可变的
    [DataContract]
    类的方式:

    namespace SomeService.Contracts
    {
        [DataContract]
        public sealed class Foo
        {
            public Foo(int x)
            {
                this.x = x;
            }
    
            public int X
            {
                get
                {
                    return x;
                }
            }
    
            [DataMember]  // NB: applied to the backing field, not to the property!
            private readonly int x;
        }
    }
    
    请注意,
    [DataMember]
    应用于支持字段,而不是相应的只读属性

  • 从您的服务应用程序项目(我称之为我的
    SomeService.Web
    )和客户机项目(我的称为
    SomeService.client
    )中引用合同程序集。这可能会导致解决方案中存在以下项目依赖关系:

  • 接下来,当您将服务引用添加到客户端项目时,请确保启用了“重用类型”选项,并确保您的合同程序集(
    SomeService.Contracts
    )将包含在以下内容中:

  • 瞧!VisualStudio不会从服务的WSDL模式中生成新的
    Foo
    类型,而是从您的合约程序集中重用不可变的
    Foo
    类型


    最后一个警告:您已经偏离了中引用的服务原则。但是不要再迷路了。您可能会开始向数据契约类添加(业务)逻辑;不要。它们应该尽可能地靠近哑数据传输对象(DTO)。

    啊,是的-正如我所说的,我尝试将字段设置为DataMember,但在客户端它没有显示为只读。但是没有办法让它在客户端成为只读的吗?没有。只读是一个C#术语,而不是SOA。您不能使XML成为ReadOnlyTanks的一部分。这似乎是除了创建特定于数据的类之外的最佳选择。。。对于小型应用程序来说,这就是太多的额外代码。你是什么意思?DataMember位于通过DataContract可用的DTO类中。我也有一份服务合同,但这在这里并没有真正的关系-是吗?这是一份数据合同,而不是一份解释得很好的服务合同。谢谢你的澄清!这些信息很好,但我不认为它直接回答了问题。所有这些都说明了目前的情况是多么荒谬。既然服务器端类只用于生成契约,为什么需要setter?如果不是因为DataContractSerializer是prissy,服务器上的实例可以在没有它们的情况下对客户端进行序列化。只有相反的情况才会导致问题。同意@atoumey。Marc,你能详细说明一下OP问题的可能解决方案吗?我在这个解决方案中看到的问题是,因为不能同时使用ISerializable和DataContract,DataContract还定义了序列化。如果您尝试序列化此对象,它将在反序列化期间引发异常。因此,与抛出异常相比,黑客明智地选择no op似乎是唯一的选择。在这种情况下,将“Total”实现为扩展方法效果很好(我知道扩展方法可能没有
    public class PricingSummary
    {
        public int TotalItemCount { get; set; } // doesnt ideally belong here but used by top bar when out of store area
    
        public decimal SubTotal { get; set; }
        public decimal? Taxes { get; set; }
        public decimal Discount { get; set; }
        public decimal? ShippingTotal { get; set; }
        public decimal Total
        {
            get
            {
                return + SubTotal
                       + (ShippingTotal ?? 0)
                       + (Taxes ?? 0)
                       - Discount;
            }
            set
            {
                throw new ApplicationException("Cannot be set");
            }
        }
    }
    
    namespace SomeService.Contracts
    {
        [DataContract]
        public sealed class Foo
        {
            public Foo(int x)
            {
                this.x = x;
            }
    
            public int X
            {
                get
                {
                    return x;
                }
            }
    
            [DataMember]  // NB: applied to the backing field, not to the property!
            private readonly int x;
        }
    }