preferirei estraggo i miei tipi personalizzati tutto in una volta e utilizzarlo durante la serializzazione/deserializzazione. Dopo aver letto questo post, mi ci è voluto un po 'per capire dove iniettare questa lista di tipi per essere utile per l'oggetto serializzatore. La risposta è stata abbastanza semplice: questa lista deve essere utilizzata come uno degli argomenti di input del costruttore dell'oggetto serializzatore.
1- sto usando due metodi generici statici per la serializzazione e deserializzazione, questo può essere più o meno come gli altri anche fare il lavoro, o almeno è molto chiaro per fare il confronto con il tuo codice:
public static byte[] Serialize<T>(T obj)
{
var serializer = new DataContractSerializer(typeof(T), MyGlobalObject.ResolveKnownTypes());
var stream = new MemoryStream();
using (var writer =
XmlDictionaryWriter.CreateBinaryWriter(stream))
{
serializer.WriteObject(writer, obj);
}
return stream.ToArray();
}
public static T Deserialize<T>(byte[] data)
{
var serializer = new DataContractSerializer(typeof(T), MyGlobalObject.ResolveKnownTypes());
using (var stream = new MemoryStream(data))
using (var reader =
XmlDictionaryReader.CreateBinaryReader(
stream, XmlDictionaryReaderQuotas.Max))
{
return (T)serializer.ReadObject(reader);
}
}
2- Prestare attenzione al costruttore di DataContractSerializer.Qui abbiamo un secondo argomento, che è il punto di ingresso per l'iniezione dei tipi noti all'oggetto serializzatore.
3- Sto utilizzando un metodo statico per estrarre tutti i miei tipi definiti dai miei stessi assiemi. il codice per questo metodo statico può apparire come segue:
private static Type[] KnownTypes { get; set; }
public static Type[] ResolveKnownTypes()
{
if (MyGlobalObject.KnownTypes == null)
{
List<Type> t = new List<Type>();
List<AssemblyName> c = System.Reflection.Assembly.GetEntryAssembly().GetReferencedAssemblies().Where(b => b.Name == "DeveloperCode" | b.Name == "Library").ToList();
foreach (AssemblyName n in c)
{
System.Reflection.Assembly a = System.Reflection.Assembly.Load(n);
t.AddRange(a.GetTypes().ToList());
}
MyGlobalObject.KnownTypes = t.ToArray();
}
return IOChannel.KnownTypes;
}
Dal momento che non è stato coinvolto in WCF (Ho solo bisogno di una serializzazione binaria per il funzionamento di file), la mia soluzione potrebbe non esattamente affrontare l'architettura WCF, ma ci deve accedere al costruttore di oggetti serializer da qualche parte.
fonte
2016-11-25 14:26:35
Se preferisci non creare il metodo di estensione, questo può essere trasformato in un unico elemento. 'return Assembly.GetExecutingAssembly(). GetTypes(). Where (_ => _.IsSubclassOf (typeof (TaskBase))). ToArray();' – x5657
Questa è un'ottima soluzione. Pulito e semplice – kenjara
Questo è un vero toccasana! –