XML serialization
interface property
data serialization
XML programming
C# serialization

XML serialization of interface property

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

XmlSerializer in .NET works best when it knows the concrete shape of every serialized object ahead of time. Interface-typed properties break that assumption, because an interface describes behavior but does not tell the serializer which concrete class should be written or reconstructed.

Why Interface Properties Fail

Consider this simple model:

csharp
1public interface IPaymentMethod
2{
3    string Kind { get; }
4}
5
6public class Order
7{
8    public string Number { get; set; } = "";
9    public IPaymentMethod PaymentMethod { get; set; }
10}

This design is fine for normal C# code, but XmlSerializer cannot directly serialize PaymentMethod. During serializer generation it needs a concrete serializable type, not an interface.

That is why code such as this typically fails:

csharp
using System.Xml.Serialization;

var serializer = new XmlSerializer(typeof(Order));

The problem appears before any XML is even written.

A Practical Workaround: Ignore The Interface, Expose A Concrete XML Property

The most common workaround is to keep the interface for your domain model while exposing a serializer-friendly property for XML:

csharp
1using System;
2using System.IO;
3using System.Xml.Serialization;
4
5public interface IPaymentMethod
6{
7    string Kind { get; }
8}
9
10public class CardPayment : IPaymentMethod
11{
12    public string Kind => "card";
13    public string Last4 { get; set; } = "";
14}
15
16public class Order
17{
18    public string Number { get; set; } = "";
19
20    [XmlIgnore]
21    public IPaymentMethod PaymentMethod { get; set; }
22
23    [XmlElement("CardPayment", typeof(CardPayment))]
24    public object PaymentMethodXml
25    {
26        get => PaymentMethod;
27        set => PaymentMethod = (IPaymentMethod)value;
28    }
29}
30
31public static class Demo
32{
33    public static void Main()
34    {
35        var order = new Order
36        {
37            Number = "A-100",
38            PaymentMethod = new CardPayment { Last4 = "4242" }
39        };
40
41        var serializer = new XmlSerializer(typeof(Order));
42        using var writer = new StringWriter();
43        serializer.Serialize(writer, order);
44        Console.WriteLine(writer.ToString());
45    }
46}

This pattern keeps the public XML contract concrete while still letting the rest of the code work with the interface.

Supporting Multiple Implementations

If the interface may point to several concrete types, each one must be declared explicitly for the XML property:

csharp
1public class BankTransferPayment : IPaymentMethod
2{
3    public string Kind => "bank";
4    public string Iban { get; set; } = "";
5}
6
7public class Order
8{
9    public string Number { get; set; } = "";
10
11    [XmlIgnore]
12    public IPaymentMethod PaymentMethod { get; set; }
13
14    [XmlElement("CardPayment", typeof(CardPayment))]
15    [XmlElement("BankTransferPayment", typeof(BankTransferPayment))]
16    public object PaymentMethodXml
17    {
18        get => PaymentMethod;
19        set => PaymentMethod = (IPaymentMethod)value;
20    }
21}

Without those explicit mappings, deserialization still has no safe way to know which concrete types are valid.

When A DTO Is Cleaner

If the XML shape is an integration boundary rather than your internal domain model, a dedicated DTO is often cleaner than forcing XML concerns into your core objects.

For example, you can create an XML model like OrderXml that uses concrete types only, then map it to the interface-based domain model after deserialization.

That separation is useful when:

  • the domain model is polymorphic
  • the XML contract is fixed by another system
  • versioning concerns differ between business logic and transport format

In those cases, a DTO can reduce attribute noise and make the serialization rules more explicit.

Common Pitfalls

One common mistake is leaving the interface property public and unignored. The serializer still sees it and fails even if you added a helper property elsewhere.

Another issue is exposing the XML-facing property as object but forgetting to declare the allowed concrete types with XML attributes.

A third problem is trying to make XmlSerializer solve deep polymorphism automatically. It is intentionally more rigid than many JSON serializers.

Finally, teams sometimes overload the domain model with transport-specific attributes until the class becomes harder to maintain than a separate DTO would have been.

Summary

  • 'XmlSerializer cannot directly serialize an interface property because interfaces are not concrete types.'
  • The usual fix is to ignore the interface property and expose a concrete XML-facing surrogate.
  • If several implementations are allowed, declare each concrete type explicitly.
  • For larger or more polymorphic models, separate XML DTOs are often cleaner than forcing XML rules into domain classes.
  • Keep the serializer contract concrete even if the internal application code stays interface-based.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.