JavaScriptTypeResolver Classe
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Fornisce la classe base astratta per l'implementazione di un resolver di tipi personalizzato.
public ref class JavaScriptTypeResolver abstract
public abstract class JavaScriptTypeResolver
type JavaScriptTypeResolver = class
Public MustInherit Class JavaScriptTypeResolver
- Ereditarietà
-
JavaScriptTypeResolver
- Derivato
Esempio
Nell'esempio seguente viene illustrato come creare un oggetto personalizzato JavaScriptTypeResolver e come usarlo per serializzare o deserializzare un oggetto.
using System;
using System.Linq;
using System.Web.Script.Serialization;
namespace SampleApp
{
class Program
{
static void Main(string[] args)
{
// The object array to serialize.
Person[] people = new Person[]
{
new Person()
{
Name = "Kristen Solstad",
Age = 15,
HomeAddress = new Address()
{
Street1 = "123 Palm Ave",
City = "Some City",
StateOrProvince = "ST",
Country = "United States",
PostalCode = "00000"
}
},
new Adult()
{
Name = "Alex Johnson",
Age = 39,
Occupation = "Mechanic",
HomeAddress = new Address()
{
Street1 = "445 Lorry Way",
Street2 = "Unit 3A",
City = "Some City",
Country = "United Kingdom",
PostalCode = "AA0 A00"
}
}
};
// Serialize the object array, then write it to the console.
string serializedData = SerializePeopleArray(people);
Console.WriteLine("Serialized:");
Console.WriteLine(serializedData);
Console.WriteLine();
// Now deserialize the object array.
Person[] deserializedArray = DeserializePeopleArray(serializedData);
Console.WriteLine("Deserialized " + deserializedArray.Length + " people.");
foreach (Person person in deserializedArray)
{
Console.WriteLine(person.Name + " (Age " + person.Age + ") [" + person.GetType() + "]");
}
}
static string SerializePeopleArray(Person[] people)
{
// The custom type resolver to use.
// Note: Except for primitives like int and string, *every* type that
// we might see in the object graph must be listed here.
CustomTypeResolver resolver = new CustomTypeResolver(
typeof(Person),
typeof(Adult),
typeof(Address));
// Instantiate the serializer.
JavaScriptSerializer serializer = new JavaScriptSerializer(resolver);
// Serialize the object array, then return it.
string serialized = serializer.Serialize(people);
return serialized;
}
static Person[] DeserializePeopleArray(string serializedData)
{
// The custom type resolver to use.
// Note: This is the same list that was provided to the Serialize routine.
CustomTypeResolver resolver = new CustomTypeResolver(
typeof(Person),
typeof(Adult),
typeof(Address));
// Instantiate the serializer.
JavaScriptSerializer serializer = new JavaScriptSerializer(resolver);
// Deserialize the object array, then return it.
Person[] deserialized = serializer.Deserialize<Person[]>(serializedData);
return deserialized;
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Address HomeAddress { get; set; }
}
public class Adult : Person
{
public string Occupation { get; set; }
}
public class Address
{
public string Street1 { get; set; }
public string Street2 { get; set; }
public string City { get; set; }
public string StateOrProvince { get; set; }
public string Country { get; set; }
public string PostalCode { get; set; }
}
// A custom JavaScriptTypeResolver that restricts the payload
// to a set of known good types.
class CustomTypeResolver : JavaScriptTypeResolver
{
private readonly Type[] _allowedTypes;
public CustomTypeResolver(params Type[] allowedTypes)
{
if (allowedTypes == null)
{
throw new ArgumentNullException("allowedTypes");
}
// Make a copy of the array the caller gave us.
_allowedTypes = (Type[])allowedTypes.Clone();
}
public override Type ResolveType(string id)
{
// Iterate over all of the allowed types, looking for a match
// for the 'id' parameter. Calling Type.GetType(id) is dangerous,
// so we instead perform a match on the Type.FullName property.
foreach (Type allowedType in _allowedTypes)
{
if (allowedType.FullName == id)
{
return allowedType;
}
}
// The caller provided a type we don't recognize. This could be
// dangerous, so we'll fail the operation immediately.
throw new ArgumentException("Unknown type: " + id, "id");
}
public override string ResolveTypeId(Type type)
{
// Before we serialize data, quickly double-check to make
// sure we're allowed to deserialize the data. Otherwise it's
// no good serializing something if we can't deserialize it.
if (_allowedTypes.Contains(type))
{
return type.FullName;
}
throw new InvalidOperationException("Cannot serialize an object of type " + type + ". Did you forget to add it to the allow list?");
}
}
}
L'app precedente restituisce quanto segue nella console, formattata per la leggibilità.
Serialized:
[
{
"__type": "SampleApp.Person",
"Name": "Kristen Solstad",
"Age": 15,
"HomeAddress": {
"__type": "SampleApp.Address",
"Street1": "123 Palm Ave",
"Street2": null,
"City": "Some City",
"StateOrProvince": "ST",
"Country": "United States",
"PostalCode": "00000"
}
},
{
"__type": "SampleApp.Adult",
"Occupation": "Mechanic",
"Name": "Alex Johnson",
"Age": 39,
"HomeAddress": {
"__type": "SampleApp.Address",
"Street1": "445 Lorry Way",
"Street2": "Unit 3A",
"City": "Some City",
"StateOrProvince": null,
"Country": "United Kingdom",
"PostalCode": "AA0 A00"
}
}
]
Deserialized 2 people.
Kristen Solstad (Age 15) [SampleApp.Person]
Alex Johnson (Age 39) [SampleApp.Adult]
Nell'esempio precedente, il Adult tipo sottoclassa il Person tipo. Un oggetto personalizzato JavaScriptTypeResolver viene usato per includere le informazioni sul tipo come parte del payload JSON generato. Ciò consente un polimorfismo limitato durante la deserializzazione del payload JSON in un oggetto grafico .NET. Il payload può controllare se restituire un'istanza di base Person o un'istanza derivata Adult al chiamante.
Questo esempio è sicuro perché usa un allow-list meccanismo per controllare la deserializzazione. Codice:
- Inizializza con un elenco esplicito di tipi consentiti
CustomTypeResolver. - Limita il processo di deserializzazione solo all'elenco approvato di tipi. La restrizione impedisce gli attacchi di deserializzazione, in cui il client remoto specifica un dannoso
__typenel payload JSON e fa in modo che il server deserializzi un tipo pericoloso.
Anche se l'app prevede Person solo la deserializzazione delle istanze e Adult come parte della matrice di primo livello, è comunque necessario aggiungere Address all'elenco elementi consentiti perché:
- La serializzazione di un
Personoggetto oAdultserializza anche un oggettoAddresscome parte dell'oggetto grafico. - Tutti i tipi che potrebbero essere presenti nell'oggetto grafico devono essere considerati nell'elenco elementi consentiti. Le primitive come
intestringnon devono essere specificate.
Avvertimento
Non chiamare Type.GetType(id) all'interno del ResolveType metodo . Questo potrebbe introdurre una sicurezza vunerability nell'app. Scorrere invece l'elenco dei tipi consentiti e confrontare la relativa Type.FullName proprietà con l'oggetto in ingresso id, come illustrato nell'esempio precedente.
Commenti
La JavaScriptTypeResolver classe fornisce i servizi per:
Conversione delle informazioni sul tipo gestito in un valore stringa tramite il ResolveTypeId metodo .
Risoluzione di un valore stringa nel tipo gestito appropriato tramite il ResolveType metodo .
Quando l'oggetto JavaScriptSerializer serializza tipi personalizzati, può includere facoltativamente nella stringa JSON (JavaScript Object Notation) serializzata un valore che contiene informazioni sul tipo. Durante la deserializzazione, JavaScriptSerializer può quindi fare riferimento a questo valore stringa per determinare il tipo gestito appropriato in cui verrà convertita la stringa JSON.
Se si fornisce un sistema di risoluzione dei tipi all'istanza JavaScriptSerializer , il serializzatore userà i ResolveTypeId metodi e ResolveType per eseguire il mapping tra il tipo gestito e il valore stringa durante il processo di serializzazione e deserializzazione, rispettivamente.
La JavaScriptTypeResolver classe è la classe base per la SimpleTypeResolver classe , che fornisce un'implementazione di un resolver di tipi che usa il nome completo dell'assembly del tipo gestito.
Note
Quando si usa un JavaScriptTypeResolveroggetto , il payload JSON risultante contiene una proprietà speciale __type . Questa proprietà include il nome completo del tipo, incluso lo spazio dei nomi, del tipo di destinazione. Prima di usare un sistema di risoluzione personalizzato, verificare che il nome completo del tipo di destinazione non contenga informazioni riservate o con privilegi.
Note per gli implementatori
Quando si implementa un sistema di risoluzione dei tipi, la stringa restituita dal metodo deve eseguire il ResolveTypeId(Type) mapping allo stesso tipo gestito quando il valore stringa viene passato al ResolveType(String) metodo .
Costruttori
| Nome | Descrizione |
|---|---|
| JavaScriptTypeResolver() |
Inizializza una nuova istanza della classe JavaScriptTypeResolver. |
Metodi
| Nome | Descrizione |
|---|---|
| Equals(Object) |
Determina se l'oggetto specificato è uguale all'oggetto corrente. (Ereditato da Object) |
| GetHashCode() |
Funge da funzione hash predefinita. (Ereditato da Object) |
| GetType() |
Ottiene il Type dell'istanza corrente. (Ereditato da Object) |
| MemberwiseClone() |
Crea una copia superficiale del Objectcorrente. (Ereditato da Object) |
| ResolveType(String) |
Quando sottoposto a override in una classe derivata, restituisce l'oggetto Type associato al nome del tipo specificato. |
| ResolveTypeId(Type) |
Quando sottoposto a override in una classe derivata, restituisce il nome del tipo per l'oggetto specificato Type . |
| ToString() |
Restituisce una stringa che rappresenta l'oggetto corrente. (Ereditato da Object) |