views:

1850

answers:

4

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 */ }
}
A: 

Define the Service contract (Interface) Before implementing the contract using the class.

solairaja
What do you mean? The DataMember is in the DTO class available through a DataContract. I have a ServiceContract too, but that's not really related here - is it?
stiank81
it's a datacontract, not a service contract
Krzysztof Koźmic
+2  A: 

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.

Krzysztof Koźmic
Ah, yeah - like noted I tried setting the field as DataMember, but it was not exposed as readonly on the client side. But there's no way to make it readonly on the client side then?
stiank81
no. READONLY is a C# term, not a SOA. You can't make part of XML readonly
Krzysztof Koźmic
+9  A: 

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):

  1. Boundaries are explicit
  2. Services are autonomous
  3. Services share schema and contract, not class
  4. Compability is based upon policy

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.

marc_s
That explains it very well. Thanks for a clarifying!
stiank81
glad I could help!
marc_s
A: 

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).

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");
        }
    }
}
Simon_Weaver