JavaScriptTypeResolver Classe

Definição

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 do Address grafo de objeto.
  • Todos os tipos que podem estar presentes no grafo de objeto precisam ser contabilados na lista de permitir. Primitivos int como string 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)

Aplica-se a