tags:

views:

268

answers:

3

I appear to be having an issue with the following snippet of code in that, when I come to specifying what the Item is (eg CashInHand), the actual type CashInHandPayment is not available because it hasn't been carried across when I generate the proxy class (most likely because it doesn't read in XmlElementAttributes).

Is there any way to force classes such as AccountPayment, CashInHandPayment and CCPayment to be serialized in the proxy class?

[DataContract]
public class Payment
{
    [XmlElementAttribute("Account", typeof(AccountPayment))]
    [XmlElementAttribute("CashInHand", typeof(CashInHandPayment))]
    [XmlElementAttribute("CreditCard", typeof(CCPayment))]
    [XmlChoiceIdentifierAttribute("ItemElementName")]
    [DataMember]
    public object Item { get; set; }
}

[DataContract]
public enum ItemElementName
{
    [EnumMember]
    Account,
    [EnumMember]
    CashInHand,
    [EnumMember]
    CreditCard
}

//This class will not be in the generated proxy class
[DataContract]
public class AccountPayment
{
    [DataMember]
    public double Amount { get; set; }
}

//classes for CashInHandPayment and CCPayment also created, but not shown.

Forgive me if 'serialize' isn't the correct term to use, if you read the question and find that it isn't, please change it accordingly!

Update - answer mentioned by Simon Svensson:

[KnownType(typeof(AccountPayment))]
[KnownType(typeof(CashInHandPayment))]
[KnownType(typeof(CCPayment))]
[DataContract]
public class Payment
{
    [XmlElementAttribute("Account", typeof(AccountPayment))]
    [XmlElementAttribute("CashInHand", typeof(CashInHandPayment))]
    [XmlElementAttribute("CreditCard", typeof(CCPayment))]
    [XmlChoiceIdentifierAttribute("ItemElementName")]
    [DataMember]
    public object Item { get; set; }
}

Many thanks, Simon!

A: 

Is there any way to force classes such as AccountPayment, CashInHandPayment and CCPayment to be serialized in the proxy class?

They need to be marked with a [DataContract] attribute, that should be sufficient, I would think.

When svcutil.exe (either launched directly from the command line, or from Visual Studio using Add Service Reference) encounters classes with the [DataContract] attribute on the class and [DataMember] on the properties (or fields), it will create a copy in the proxy for those classes.

Marc

marc_s
Marc, As shown in the code with the AccountPayment as an example, the classes have the DataContractAttribute set.
Dan Atkinson
OK - well, you got your perfect answer already, it seems!
marc_s
+2  A: 

Uhm. Isnt XmlElementAttribute and XmlChoiceIdentifierAttribute xml serialization, which is a older serialization compared to the DataContractSerializer which reads DataContractAttribute and DataMemberAttribute?

I believe that you should use the KnownTypeAttribute for this, but I have never tried it, nor have I had this scenario in my own code.

Simon Svensson
Yes, you are right, it is part of an older serialization (from the original XSD). To pull these into the proxy class, I had to apply KnownType to the Payment class.Many thanks!
Dan Atkinson
A: 

I think specifying DataContract should be sufficient. But, if that isn't working, why not try creating a dummy OperationContract method that uses the class?

Larry Watanabe
This was going to be my very last resort, as I knew it would work, and I knew it was unbelievably hacky. :) I do agree though that the DataContract should be sufficient, but it seems that if you create a service which references most of your classes used, when the proxy is generated, it leaves out the unused ones, even if you apply DataContract to all of them.
Dan Atkinson