JavaScriptTypeResolver Klass

Definition

Tillhandahåller den abstrakta basklassen för implementering av en anpassad typlösare.

public ref class JavaScriptTypeResolver abstract
public abstract class JavaScriptTypeResolver
type JavaScriptTypeResolver = class
Public MustInherit Class JavaScriptTypeResolver
Arv
JavaScriptTypeResolver
Härledda

Exempel

I följande exempel visas hur du skapar en anpassad JavaScriptTypeResolver och hur du använder den för att serialisera eller deserialisera ett objekt.

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

Föregående app matar ut följande till konsolen, formaterad för läsbarhet.

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]

I föregående exempel Adult klassificerar typen underklasser Person . En anpassad JavaScriptTypeResolver används för att inkludera typinformationen som en del av den genererade JSON-nyttolasten. Detta tillåter begränsad polymorfism när JSON-nyttolasten deserialiseras tillbaka till ett .NET objektdiagram. Nyttolasten kan styra om en basinstans Person eller en härledd Adult instans ska returneras till anroparen.

Det här exemplet är säkert eftersom det använder en allow-list mekanism för att kontrollera deserialisering. Koden:

  • Initierar CustomTypeResolver med en explicit lista över tillåtna typer.
  • Begränsar deserialiseringsprocessen till endast godkänd lista över typer. Begränsningen förhindrar deserialiseringsattacker, där fjärrklienten anger ett skadligt i __type JSON-nyttolasten och lurar servern att deserialisera en farlig typ.

Även om appen bara förväntar sig Person att och Adult instanser ska deserialiseras som en del av matrisen på den översta nivån, är det fortfarande nödvändigt att lägga Address till i listan över tillåtna eftersom:

  • Serialisering av en Person eller Adult serialiserar även en Address som en del av objektdiagrammet.
  • Alla typer som kan finnas i objektdiagrammet måste redovisas i listan över tillåtna. Primitiver gillar int och string behöver inte anges.

Varning

Anropa inte Type.GetType(id) i ResolveType -metoden. Detta kan innebära en säkerhetsupplevelse i appen. Iterera i stället igenom listan över tillåtna typer och jämför deras Type.FullName egenskap med den inkommande id, som du ser i föregående exempel.

Kommentarer

Klassen JavaScriptTypeResolver tillhandahåller tjänsterna för:

  • Konvertera information av hanterad typ till ett strängvärde via ResolveTypeId metoden.

  • Matcha ett strängvärde tillbaka till lämplig hanterad typ via ResolveType metoden.

JavaScriptSerializer När objektet serialiserar anpassade typer kan det eventuellt inkludera ett värde som innehåller typinformation i den serialiserade JSON-strängen (JavaScript Object Notation). Under deserialiseringen JavaScriptSerializer kan du sedan referera till det här strängvärdet för att fastställa lämplig hanterad typ som JSON-strängen ska konverteras till.

Om du anger en typlösare för instansen JavaScriptSerializer använder ResolveTypeId serialiseraren metoderna och ResolveType för att mappa mellan den hanterade typen och strängvärdet under serialiserings- respektive deserialiseringsprocessen.

Klassen JavaScriptTypeResolver är basklassen SimpleTypeResolver för klassen, som tillhandahåller en implementering av en typmatchare som använder sammansättningskvalificerat namn av hanterad typ.

Note

När du använder en JavaScriptTypeResolverinnehåller den resulterande JSON-nyttolasten en särskild __type egenskap. Den här egenskapen innehåller det fullständiga typnamnet, inklusive namnområdet, för måltypen. Innan du använder en anpassad matchare kontrollerar du att det fullständiga namnet på måltypen inte innehåller känslig eller privilegierad information.

Anteckningar till implementerare

När du implementerar en typlösare måste strängen ResolveTypeId(Type) som returneras av metoden mappas tillbaka till samma hanterade typ när strängvärdet skickas till ResolveType(String) metoden.

Konstruktorer

Name Description
JavaScriptTypeResolver()

Initierar en ny instans av JavaScriptTypeResolver klassen.

Metoder

Name Description
Equals(Object)

Avgör om det angivna objektet är lika med det aktuella objektet.

(Ärvd från Object)
GetHashCode()

Fungerar som standard-hash-funktion.

(Ärvd från Object)
GetType()

Hämtar den aktuella instansen Type .

(Ärvd från Object)
MemberwiseClone()

Skapar en ytlig kopia av den aktuella Object.

(Ärvd från Object)
ResolveType(String)

När det åsidosätts i en härledd klass returnerar det Type objekt som är associerat med det angivna typnamnet.

ResolveTypeId(Type)

När det åsidosättas i en härledd klass returneras typnamnet för det angivna Type objektet.

ToString()

Returnerar en sträng som representerar det aktuella objektet.

(Ärvd från Object)

Gäller för