JavaScriptTypeResolver Classe
Definição
Importante
Algumas informações dizem respeito a um produto pré-lançado que pode ser substancialmente modificado antes de ser lançado. A Microsoft não faz garantias, de forma expressa ou implícita, em relação à informação aqui apresentada.
Fornece a classe base abstrata para implementar um resolvedor de tipos personalizado.
public ref class JavaScriptTypeResolver abstract
public abstract class JavaScriptTypeResolver
type JavaScriptTypeResolver = class
Public MustInherit Class JavaScriptTypeResolver
- Herança
-
JavaScriptTypeResolver
- Derivado
Exemplos
O exemplo seguinte mostra como criar um custom JavaScriptTypeResolver e como usá-lo para serializar ou desserializar um objeto.
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?");
}
}
}
A aplicação anterior envia o seguinte para a consola, formatado para maior legibilidade.
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]
Na amostra anterior, o Adult tipo subclasse o Person tipo. É usado um custom JavaScriptTypeResolver para incluir a informação do tipo como parte da carga útil JSON gerada. Isto permite um polimorfismo limitado ao desserializar a carga útil JSON de volta para um grafo de objetos .NET. A carga útil pode controlar se devolve uma instância base Person ou uma instância derivada Adult ao chamador.
Esta amostra é segura porque utiliza um allow-list mecanismo para controlar a desserialização. O código:
- Inicializa o
CustomTypeResolvercom uma lista explícita de tipos permitidos. - Restringe o processo de desserialização apenas a listas aprovadas de tipos. A restrição impede ataques de desserialização, onde o cliente remoto especifica um malicioso
__typena carga útil JSON e engana o servidor para desserializar um tipo perigoso.
Embora a aplicação apenas espere Person que Adult as instâncias sejam desserializadas como parte do array de topo, continua a ser necessário adicionar Address à lista de permissões porque:
- Serializar a
PersonouAdulttambém serializa umAddresscomo parte do grafo objeto. - Todos os tipos que possam estar presentes no grafo-objeto têm de ser contabilizados na lista de permitidos. Primitivos como
intestringnão precisam de ser especificados.
Warning
Não ligue Type.GetType(id) para dentro do ResolveType processo. Isto pode introduzir uma vulnerabilidade de segurança na aplicação. Em vez disso, iterar pela lista de tipos permitidos e comparar a sua Type.FullName propriedade com a entrada id, como mostrado na amostra anterior.
Observações
A JavaScriptTypeResolver aula presta os serviços para:
Converter informação de tipo gerido para um valor de cadeia através do ResolveTypeId método.
Resolver um valor de string de volta ao tipo gerido apropriado através do ResolveType método.
Quando o JavaScriptSerializer objeto serializa tipos personalizados, pode opcionalmente incluir na cadeia de Notação de Objetos JavaScript (JSON) serializada um valor que contenha informação de tipos. Durante a desserialização, JavaScriptSerializer pode então referenciar este valor da cadeia para determinar o tipo gerido apropriado para o qual a cadeia JSON será convertida.
Se fornecer um resolvedor de tipos à JavaScriptSerializer instância, o serializador usará os ResolveTypeId métodos e ResolveType para mapear entre o tipo gerido e o valor da string durante o processo de serialização e desserialização, respetivamente.
A JavaScriptTypeResolver classe é a classe base da SimpleTypeResolver classe, que fornece uma implementação de um resolver de tipos que utiliza o nome managed type assembly-qualificado.
Note
Ao usar um JavaScriptTypeResolver, a carga útil JSON resultante contém uma propriedade especial __type . Esta propriedade inclui o nome completo do tipo, incluindo o espaço de nomes, do tipo alvo. Antes de usar um resolvedor personalizado, verifique se o nome completo do tipo de destino não contém informação sensível ou privilegiada.
Notas para Implementadores
Quando implementas um resolvedor de tipos, a cadeia que é devolvida pelo ResolveTypeId(Type) método deve corresponder ao mesmo tipo gerido quando o valor da cadeia é passado para o ResolveType(String) método.
Construtores
| Name | Description |
|---|---|
| JavaScriptTypeResolver() |
Inicializa uma nova instância da JavaScriptTypeResolver classe. |
Métodos
| Name | Description |
|---|---|
| Equals(Object) |
Determina se o objeto especificado é igual ao objeto atual. (Herdado de Object) |
| GetHashCode() |
Serve como função de hash predefinida. (Herdado de Object) |
| GetType() |
Obtém o Type da instância atual. (Herdado de Object) |
| MemberwiseClone() |
Cria uma cópia superficial do atual Object. (Herdado de Object) |
| ResolveType(String) |
Quando sobrescrito numa classe derivada, devolve o Type objeto associado ao nome do tipo especificado. |
| ResolveTypeId(Type) |
Quando sobrescrito numa classe derivada, devolve o nome do tipo para o objeto especificado Type . |
| ToString() |
Devolve uma cadeia que representa o objeto atual. (Herdado de Object) |