DataContractSerializer is contract-based, meaning it is not tied to any specific type model. All it has is data (typically xml). This means that if you have a model like:
Customer
SuperCustomer : Customer
AwesomeCustomer : Customer
then the serializer needs to know in advance what each type means if it sees it in the data; otherwise it won't know what type to create. This is done in a number of ways, the simplest of which is KnownTypeAttribute.
Consider the alternative; all the serializer knows is "Customer", which it expects to see as ...
in some xml. Instead, it gets something else (it doesn't matter what, but let's say ...
. Now what does it do? Does it start scrounging for likely looking types? that is very imprecise and risky. Also consider, it needs to be able to generate a WSDL/MEX export for this data - if all it knows about is "Customer", it can't possible warn callers to also expect SuperCustomer / AwesomeCustomer - which would mean the WSDL/MEX is incomplete and useless.
This same approach is used by XmlSerializer (XmlIncludeAttribute) and protobuf-net (ProtoIncludeAttribute), and probably my most contract based serializers.
The alternative is type based serializers (BinaryFormatter, NetDataContractSerializer, etc) - in this it includes the type in the data, meaning Your.Namespace.Type, Your.Assembly, blah
- this means it doesn't need to know in advance (since it is explicit in the data), but also means that it can't possibly work for different models (or indeed, cross-platform).