WCF:公开未设置的只读 DataMember 属性?
我有一个服务器端类,我通过 [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]
public int Id
{
get { return _id; }
private set { /* NOOP */ }
}
I have a server side class which I make available on the client side through a [DataContract]. This class has a readonly field which I'd like to make available through a property. However, I'm unable to do so because it doesn't seem that I'm allowed to add a [DataMember] property without having both get and set.
So - is there a way to have a [DataMember] property without setter?
[DataContract]
class SomeClass
{
private readonly int _id;
public SomeClass() { .. }
[DataMember]
public int Id { get { return _id; } }
[DataMember]
public string SomeString { get; set; }
}
Or will the solution be use the [DataMember] as the field - (like e.g. shown here)? Tried doing this too, but it doesn't seem to care the field is readonly..?
Edit: Is the only way to make a readonly property by hacking it like this? (no - I don't want to do this...)
[DataMember]
public int Id
{
get { return _id; }
private set { /* NOOP */ }
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
实际上,您的“服务器端”类不会对客户端“可用”。
发生的情况是这样的:根据数据契约,客户端将从服务的 XML 模式创建一个新的单独类。它不能使用服务器端类本身!
它将根据 XML 架构定义重新创建一个新类,但该架构不包含任何 .NET 特定的内容,例如可见性或访问修饰符 - 毕竟它只是一个 XML 架构。客户端类将以这样的方式创建,即它在线路上具有相同的“足迹” - 例如,它基本上序列化为相同的 XML 格式。
您无法通过标准的基于 SOAP 的服务“传输”有关该类的 .NET 特定知识 - 毕竟,您传递的只是序列化消息 - 不上课!
检查“SOA 的四个原则”(由 Microsoft 的 Don Box 定义):
请参阅第 3 点 - 服务共享架构和契约,不是类 - 您只共享数据协定的接口和 XML 架构 - 仅此而已 - 没有 .NET 类。
Your "server-side" class won't be "made available" to the client, really.
What happens is this: based on the data contract, the client will create a new separate class from the XML schema of the service. It cannot use the server-side class per se!
It will re-create a new class from the XML schema definition, but that schema doesn't contain any of the .NET specific things like visibility or access modifiers - it's just a XML schema, after all. The client-side class will be created in such a way that it has the same "footprint" on the wire - e.g. it serializes into the same XML format, basically.
You cannot "transport" .NET specific know-how about the class through a standard SOAP-based service - after all, all you're passing around are serialized messages - no classes!
Check the "Four tenets of SOA" (defined by Don Box of Microsoft):
See point #3 - services share schema and contract, not class - you only ever share the interface and XML schema for the data contract - that's all - no .NET classes.
将 DataMember 属性放在字段而不是属性上。
请记住,WCF 不知道封装。封装是一个 OOP 术语,而不是 SOA 术语。
也就是说,请记住,该字段对于使用您的类的人来说是只读的 - 使用该服务的任何人都可以完全访问他们这边的字段。
put DataMember attribute on a field not the property.
Remember thought, that WCF does not know encapsulation. Encapsulation is a OOP term, not a SOA term.
That said, remember that the field will be readonly for people using your class - anyone using the service will have full access to the field on their side.
有一种方法可以实现这一目标。但请注意,它直接违反了此答案中引用的以下原则:
如果您不关心此违规行为,则可以执行以下操作:
将服务和数据协定移至单独的(可移植)类库中。 (我们将此程序集称为
SomeService.Contracts
。)这就是定义不可变[DataContract]
类的方式:请注意,
[DataMember]
应用于支持字段,而不是应用于相应的只读属性。从您的服务应用程序项目(我将其称为
SomeService.Web
)和您的客户端项目(我的称为SomeService.Client
)中引用合约程序集。这可能会导致您的解决方案中出现以下项目依赖项:接下来,当将服务引用添加到客户端项目中,确保启用“重用类型”选项,并确保您的合约程序集 (
SomeService.Contracts
) 将包含在其中:瞧! Visual Studio 不会从服务的 WSDL 架构生成新的
Foo
类型,而是重用合约程序集中的不可变Foo
类型。最后一个警告:您已经偏离了其他答案中引用的服务原则。但尽量不要再偏离正轨。您可能想开始向数据协定类添加(业务)逻辑;不。它们应该尽可能靠近哑数据传输对象 (DTO)。
There is a way to achieve this. But be warned that it directly violates the following principle cited in this answer:
If this violation does not concern you, this is what you do:
Move the service and data contracts into a separate (portable) class library. (Let's call this assembly
SomeService.Contracts
.) This is how you'd define an immutable[DataContract]
class:Note that
[DataMember]
is applied to the backing field, and not to the corresponding read-only property.Reference the contract assembly from both your service application project (I'll call mine
SomeService.Web
) and from your client projects (mine is calledSomeService.Client
). This might result in the following project dependencies inside your solution:Next, when you add the service reference to your client project, make sure to have the option "reuse types" enabled, and ensure that your contract assembly (
SomeService.Contracts
) will be included in this:Voilà! Visual Studio, instead of generating a new
Foo
type from the service's WSDL schema, will reuse the immutableFoo
type from your contract assembly.One last warning: You've already strayed from the service principles cited in that other answer. But try not to stray any further. You might be tempted to start adding (business) logic to your data contract classes; don't. They should stay as close to dumb data transfer objects (DTOs) as you can manage.
我的服务层中的一个类中有一些属性,我想传递给 Silverlight。我不想创建一个全新的类。
并不是真正“推荐”,但这似乎是将
Total
属性传递给 silverlight(仅用于可视数据绑定)的两害相权取其轻。I had some properties in a class in my service layer I wanted to pass over to Silverlight. I didn't want to create a whole new class.
Not really 'recommended', but this seemed the lesser of two evils to pass over the
Total
property to silverlight (solely for visual databinding).定义服务契约(接口) 在使用类实现契约之前。
Define the Service contract (Interface) Before implementing the contract using the class.