The short answer is you can't. At least not without some trickery and giving the serializer some help, and even then it's not pretty.
Here's the plain-jane implementation. Note: The following snippet WILL NOT WORK
public interface IWorker
{
string WorkerName { get; set; }
}
[Serializable]
public class ImplementedWorker:IWorker
{
#region IWorker Members
public string WorkerName { get; set; }
#endregion
}
[Serializable]
public class WorkToDo
{
public IWorker Worker;
}
public void Tryme()
{
WorkToDo workToDo = new WorkToDo();
workToDo.Worker = new ImplementedWorker();
}
If you try to serialize the WorkToDo class, you'll get the "cannot serialize Worker because IWorker is an interface" exception. This makes sense when you consider the XML serializer will have to deserialize this into some concrete type.
So let's give it a type. since we don't want to lose the ability to enforce the implementation of our interface properties, we're going to make an Abstract class.
public interface IWorker
{
string WorkerName { get; set; }
}
[Serializable]
public abstract class WorkerBase : IWorker
{
public abstract string WorkerName { get; set; }
}
[Serializable]
public class ImplementedWorker : WorkerBase
{
#region IWorker Members
public override string WorkerName { get; set; }
#endregion
}
[Serializable]
public class WorkToDo
{
public WorkerBase Worker;
}
Notice that we change the defintion of the implementation class(ImplementedWorker) from the interface to the abstract class. we're almost there, but the serializer still can't deserialize this to a concrete type. This is where we have to give the serializer some help in the form of the XMLIncludeAttribute. The XMLIncludeAttribute tells the serializer "this thing might be this concrete type", you can stack multiple XMLInclude attributes on your abstract class definition, and during serialization, it figures out the correct concrete type to use.
public interface IWorker
{
string WorkerName { get; set; }
}
[Serializable]
[XmlInclude(typeof(ImplementedWorker))]
public abstract class WorkerBase : IWorker
{
public abstract string WorkerName { get; set; }
}
[Serializable]
public class ImplementedWorker : WorkerBase
{
#region IWorker Members
public override string WorkerName { get; set; }
#endregion
}
[Serializable]
public class WorkToDo
{
public WorkerBase Worker;
}
WorkToDo will now properly serialize using the XMLSerializer. Here's the downside (and its a biggie), every time you add a new subclass of your abstract class, you've got the remember to add another XMLInclude attribute for it in the abstract class definition. I told you it wasn't going to be pretty.
An alternate approach would be to write your own custom serializer for the type, but that's a post for a different day.