JavaScriptTypeResolver Klasa
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
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 zwraca 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 subklasuje Person typ.
JavaScriptTypeResolver Niestandardowy element służy do uwzględnienia informacji o typie w ramach wygenerowanego ładunku JSON. Dzięki temu można ograniczyć polimorfizm podczas deserializacji ładunku JSON z powrotem do wykresu obiektów .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 obiekt
CustomTypeResolverz jawną listą dozwolonych typów. - Ogranicza proces deserializacji tylko do zatwierdzonej listy typów. Ograniczenie zapobiega atakom deserializacji, gdzie klient zdalny określa złośliwy
__typeładunek JSON i utrudnia serwerowi deserializacji niebezpiecznego typu.
Mimo że aplikacja oczekuje Person tylko deserializacji wystąpień i Adult w ramach tablicy najwyższego poziomu, nadal trzeba dodać Address je do listy dozwolonych, ponieważ:
- Serializowanie elementu
PersonlubAdultrównież serializujeAddresselement jako część grafu obiektu. - Wszystkie typy, które mogą znajdować się na grafie obiektów, muszą być uwzględniane na liście dozwolonych. Elementy pierwotne, takie jak
intistringnie muszą być określone.
Warning
Nie należy wywoływać Type.GetType(id) metody ResolveType . Może to spowodować vunerability zabezpieczeń w aplikacji. Zamiast tego wykonaj iterację po liście 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 .
JavaScriptSerializer Gdy obiekt serializuje typy niestandardowe, opcjonalnie może zawierać w ciągu serializowanego kodu 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 JavaScriptSerializer typów dla wystąpienia, serializator użyje ResolveTypeId metod i ResolveType do mapowania między typem zarządzanym a wartością ciągu odpowiednio podczas procesu serializacji i deserializacji.
Klasa JavaScriptTypeResolver jest klasą bazową klasy SimpleTypeResolver , która zapewnia implementację rozpoznawania typów, która używa zarządzanej nazwy kwalifikowanej przez zestaw typów.
Note
W przypadku używania elementu wynikowy JavaScriptTypeResolverł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 rozpoznawania nazw sprawdź, czy pełna nazwa typu docelowego nie zawiera poufnych ani uprzywilejowanych informacji.
Notatki 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
| Nazwa | Opis |
|---|---|
| JavaScriptTypeResolver() |
Inicjuje nowe wystąpienie klasy JavaScriptTypeResolver. |
Metody
| Nazwa | Opis |
|---|---|
| Equals(Object) |
Określa, czy określony obiekt jest równy bieżącemu obiektowi. (Odziedziczone po Object) |
| GetHashCode() |
Służy jako domyślna funkcja skrótu. (Odziedziczone po Object) |
| GetType() |
Pobiera Type bieżącego wystąpienia. (Odziedziczone po Object) |
| MemberwiseClone() |
Tworzy płytkią kopię bieżącego Object. (Odziedziczone po Object) |
| ResolveType(String) |
Po zastąpieniu w klasie pochodnej zwraca Type obiekt skojarzony z określoną nazwą typu. |
| ResolveTypeId(Type) |
Po zastąpieniu w klasie pochodnej zwraca nazwę typu określonego Type obiektu. |
| ToString() |
Zwraca ciąg reprezentujący bieżący obiekt. (Odziedziczone po Object) |