Udostępnij za pośrednictwem


JavaScriptTypeResolver Klasa

Definicja

Udostępnia abstrakcyjną klasę bazową do implementowania niestandardowego rozpoznawania typów.

public ref class JavaScriptTypeResolver abstract
public abstract class JavaScriptTypeResolver
type JavaScriptTypeResolver = class
Public MustInherit Class JavaScriptTypeResolver
Dziedziczenie
JavaScriptTypeResolver
Pochodne

Przykłady

W poniższym przykładzie pokazano, jak utworzyć niestandardowy i JavaScriptTypeResolver jak używać go do serializacji lub deserializacji obiektu.

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?");
        }
    }
}

Poprzednia aplikacja generuje następujące dane do konsoli, sformatowane pod kątem czytelności.

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]

W poprzednim przykładzie Adult typ podklasuje Person typ. Element niestandardowy JavaScriptTypeResolver służy do uwzględnienia informacji o typie w ramach wygenerowanego ładunku JSON. Pozwala to ograniczyć polimorfizm podczas deserializacji ładunku JSON z powrotem do grafu obiektów platformy .NET. Ładunek może kontrolować, czy zwracać wystąpienie podstawowe Person , czy wystąpienie pochodne Adult z powrotem do obiektu wywołującego.

Ten przykład jest bezpieczny, ponieważ używa allow-list mechanizmu do kontrolowania deserializacji. Kod:

  • Inicjuje element CustomTypeResolver z jawną listą dozwolonych typów.
  • Ogranicza proces deserializacji tylko do zatwierdzonej listy typów. Ograniczenie zapobiega atakom deserializacji, w którym klient zdalny określa złośliwy __type ładunek JSON i oszuka serwer do deserializacji niebezpiecznego typu.

Mimo że aplikacja oczekuje Person tylko deserializacji wystąpień w Adult ramach tablicy najwyższego poziomu, nadal trzeba dodać Address do listy dozwolonych, ponieważ:

  • Serializowanie elementu Person lub Adult serializuje Address element jako część grafu obiektu.
  • Wszystkie typy, które mogą być obecne na grafie obiektów, muszą być uwzględniane na liście dozwolonych. Elementy pierwotne, takie jak int i string nie muszą być określone.

Ostrzeżenie

Nie należy wywoływać Type.GetType(id) w metodzie ResolveType . Może to spowodować vunerability zabezpieczeń w aplikacji. Zamiast tego iteruj listę dozwolonych typów i porównaj ich Type.FullName właściwość z przychodzącym idelementem , jak pokazano w poprzednim przykładzie.

Uwagi

Klasa JavaScriptTypeResolver udostępnia usługi dla:

  • Konwertowanie informacji o typie zarządzanym na wartość ciągu za pomocą ResolveTypeId metody .

  • Rozpoznawanie wartości ciągu z powrotem do odpowiedniego typu zarządzanego ResolveType za pomocą metody .

Gdy JavaScriptSerializer obiekt serializuje typy niestandardowe, może on opcjonalnie uwzględniać w serializowanym ciągu JavaScript Object Notation (JSON) wartość zawierającą informacje o typie. Podczas deserializacji można odwoływać się do tej wartości ciągu, JavaScriptSerializer aby określić odpowiedni typ zarządzany, do którego zostanie przekonwertowany ciąg JSON.

Jeśli podasz rozpoznawanie typów do JavaScriptSerializer wystąpienia, serializator użyje ResolveTypeId metod i ResolveType do mapowania między typem zarządzanym a wartością ciągu podczas procesu serializacji i deserializacji, odpowiednio.

Klasa JavaScriptTypeResolver jest klasą bazową klasy SimpleTypeResolver , która zapewnia implementację rozpoznawania typów, która używa nazwy kwalifikowanej przez zestaw typu zarządzanego.

Uwaga

W przypadku korzystania z elementu JavaScriptTypeResolverwynikowy ładunek JSON zawiera właściwość specjalną __type . Ta właściwość zawiera pełną nazwę typu, w tym przestrzeń nazw, typu docelowego. Przed użyciem niestandardowego narzędzia rozpoznawania sprawdź, czy pełna nazwa typu docelowego nie zawiera poufnych ani uprzywilejowanych informacji.

Uwagi dotyczące implementowania

Podczas implementowania rozpoznawania typów ciąg zwracany przez ResolveTypeId(Type) metodę musi być mapowany z powrotem na ten sam typ zarządzany, gdy wartość ciągu jest przekazywana do ResolveType(String) metody.

Konstruktory

JavaScriptTypeResolver()

Inicjuje nowe wystąpienie klasy JavaScriptTypeResolver.

Metody

Equals(Object)

Określa, czy dany obiekt jest taki sam, jak bieżący obiekt.

(Odziedziczone po Object)
GetHashCode()

Służy jako domyślna funkcja skrótu.

(Odziedziczone po Object)
GetType()

Type Pobiera bieżące wystąpienie.

(Odziedziczone po Object)
MemberwiseClone()

Tworzy płytkią kopię bieżącego Objectelementu .

(Odziedziczone po Object)
ResolveType(String)

W przypadku zastąpienia w klasie pochodnej zwraca Type obiekt skojarzony z określoną nazwą typu.

ResolveTypeId(Type)

Po przesłonięciu w klasie pochodnej zwraca nazwę typu określonego Type obiektu.

ToString()

Zwraca ciąg reprezentujący bieżący obiekt.

(Odziedziczone po Object)

Dotyczy