JavaScriptTypeResolver Classe
Definição
Importante
Algumas informações se referem a produtos de pré-lançamento que podem ser substancialmente modificados antes do lançamento. A Microsoft não oferece garantias, expressas ou implícitas, das informações aqui fornecidas.
Fornece a classe base abstrata para implementar um resolvedor de tipo personalizado.
public ref class JavaScriptTypeResolver abstract
public abstract class JavaScriptTypeResolver
type JavaScriptTypeResolver = class
Public MustInherit Class JavaScriptTypeResolver
- Herança
-
JavaScriptTypeResolver
- Derivado
Exemplos
O exemplo a seguir mostra como criar um personalizado JavaScriptTypeResolver
e como usá-lo para serializar ou desterializar 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?");
}
}
}
O aplicativo anterior saída o seguinte para o console, formatado para capacidade de leitura.
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]
No exemplo anterior, o Adult
tipo subclasses do Person
tipo. Um personalizado JavaScriptTypeResolver
é usado para incluir as informações de tipo como parte do payload JSON gerado. Isso permite polimorfismo limitado ao desserializar o payload JSON de volta em um grafo de objeto .NET. O payload pode controlar se uma instância base ou uma instância derivada deve ser Person
Adult
retornada ao chamador.
Este exemplo é seguro porque usa um allow-list
mecanismo para controlar a desserlização. O código:
- Inicializa o com
CustomTypeResolver
uma lista explícita de tipos permitidos. - Restringe o processo de desserialização apenas à lista de tipos aprovada. A restrição impede ataques de desserialização,em que o cliente remoto especifica um mal-intencionado no conteúdo JSON e truques do servidor para
__type
desserializar um tipo perigoso.
Embora o aplicativo espere que apenas instâncias e sejam Person
desserlizadas como parte da matriz de nível superior, ainda é necessário adicionar à lista de permitir Adult
Address
porque:
- Serializar um
Person
Adult
ou também serializa um como parte doAddress
grafo de objeto. - Todos os tipos que podem estar presentes no grafo de objeto precisam ser contabilados na lista de permitir. Primitivos
int
comostring
e não precisam ser especificados.
Aviso
Não chame Type.GetType(id)
dentro do método ResolveType
. Isso pode introduzir uma capacidade de segurança para o aplicativo. Em vez disso, itere pela lista de tipos permitidos e compare sua propriedade com o de entrada, conforme Type.FullName
mostrado no exemplo id
anterior.
Comentários
A JavaScriptTypeResolver classe fornece os serviços para:
Convertendo informações de tipo gerenciado em um valor de cadeia de caracteres por meio do ResolveTypeId método .
Resolvendo um valor de cadeia de caracteres de volta para o tipo gerenciado apropriado por meio do ResolveType método .
Quando o objeto serializa tipos personalizados, ele pode opcionalmente incluir na cadeia de JavaScriptSerializer caracteres JSON (JavaScript Object Notation serializado) um valor que contém informações de tipo. Durante a desseerlização, o pode referenciar esse valor de cadeia de caracteres para determinar o tipo gerenciado apropriado no qual a cadeia de caracteres JavaScriptSerializer JSON será convertida.
Se você fornecer um resolvedor de tipo para a instância, o serializador usará os métodos e para mapear entre o tipo gerenciado e o valor da cadeia de caracteres durante o processo de serialização e JavaScriptSerializer ResolveTypeId ResolveType desselização, respectivamente.
A classe é a classe base para a classe , que fornece uma implementação de um resolvedor de tipo que usa o nome qualificado pelo JavaScriptTypeResolver SimpleTypeResolver assembly do tipo gerenciado.
Observação
Ao usar um JavaScriptTypeResolver
, o conteúdo JSON resultante contém uma propriedade __type
especial. Essa propriedade inclui o nome completo do tipo, incluindo namespace, do tipo de destino. Antes de usar um resolvedor personalizado, verifique se o nome completo do tipo de destino não contém informações confidenciais ou privilegiadas.
Notas aos Implementadores
Quando você implementa um resolvedor de tipo, a cadeia de caracteres retornada pelo método deve ser mapeada de volta para o mesmo tipo gerenciado quando o valor da cadeia de caracteres é ResolveTypeId(Type) passado para o método ResolveType(String) .
Construtores
JavaScriptTypeResolver() |
Inicializa uma nova instância da classe JavaScriptTypeResolver. |
Métodos
Equals(Object) |
Determina se o objeto especificado é igual ao objeto atual. (Herdado de Object) |
GetHashCode() |
Serve como a função de hash padrão. (Herdado de Object) |
GetType() |
Obtém o Type da instância atual. (Herdado de Object) |
MemberwiseClone() |
Cria uma cópia superficial do Object atual. (Herdado de Object) |
ResolveType(String) |
Quando substituído em uma classe derivada, retorna o objeto Type que está associado com o nome do tipo especificado. |
ResolveTypeId(Type) |
Quando substituído em uma classe derivada, retorna o nome do tipo para o objeto Type especificado. |
ToString() |
Retorna uma cadeia de caracteres que representa o objeto atual. (Herdado de Object) |