JavaScriptTypeResolver Класс
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Предоставляет абстрактный базовый класс для реализации пользовательского сопоставителя типов.
public ref class JavaScriptTypeResolver abstract
public abstract class JavaScriptTypeResolver
type JavaScriptTypeResolver = class
Public MustInherit Class JavaScriptTypeResolver
- Наследование
-
JavaScriptTypeResolver
- Производный
Примеры
В следующем примере показано, как создать настраиваемый JavaScriptTypeResolver и как использовать его для сериализации или десериализации объекта.
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?");
}
}
}
Предыдущее приложение выводит следующее в консоль, отформатированный для удобства чтения.
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]
В предыдущем примере Adult подкласс типа будет подклассом Person типа. Пользователь JavaScriptTypeResolver используется для включения сведений о типе в составе созданной полезных данных JSON. Это позволяет ограничить полиморфизм при десериализации полезных данных JSON обратно в граф объектов .NET. Полезные данные могут управлять возвратом базового Person экземпляра или производного Adult экземпляра обратно вызывающей стороне.
Этот пример является безопасным, так как он использует allow-list механизм для управления десериализацией. Код:
- Инициализирует
CustomTypeResolverявный список разрешенных типов. - Ограничивает процесс десериализации только утвержденным списком типов. Ограничение предотвращает атаки десериализации, когда удаленный клиент указывает злоумышленника
__typeв полезных данных JSON и обманывает сервер в десериализации опасного типа.
Несмотря на то, что приложение ожидает Person десериализации только экземпляров в Adult составе массива верхнего уровня, все равно необходимо добавить Address в список разрешений, так как:
- Сериализация или
PersonAdultсериализацияAddressв составе графа объектов. - Все типы, которые могут присутствовать в графе объектов, необходимо учитывать в списке разрешений. Примитивы, как
intиstringне нужно указывать.
Предупреждение
Не вызывайте Type.GetType(id) в методе ResolveType . Это может привести к доступности безопасности в приложении. Вместо этого выполните итерацию по списку разрешенных типов и сравните их Type.FullName свойство с входящим id, как показано в предыдущем примере.
Комментарии
Класс JavaScriptTypeResolver предоставляет службы для:
Преобразование сведений управляемого типа в строковое значение с помощью ResolveTypeId метода.
Разрешение строкового значения обратно в ResolveType соответствующий управляемый тип с помощью метода.
JavaScriptSerializer При сериализации пользовательских типов объект может дополнительно включать в сериализованную строку нотации объектов JavaScript (JSON) значение, содержащее сведения о типе. Во время десериализации можно ссылаться на это строковое значение, JavaScriptSerializer чтобы определить соответствующий управляемый тип, в который будет преобразована строка JSON.
Если вы предоставляете сопоставитель JavaScriptSerializer типов экземпляру, сериализатор будет использовать ResolveTypeId методы и ResolveType методы для сопоставления между управляемым типом и строковым значением во время процесса сериализации и десериализации соответственно.
Класс JavaScriptTypeResolver является базовым классом для SimpleTypeResolver класса, который предоставляет реализацию сопоставителя типов, использующего полное имя сборки управляемого типа.
Note
При использовании полученной JavaScriptTypeResolverполезные данные JSON содержат специальное __type свойство. Это свойство включает полное имя типа, включая пространство имен целевого типа. Перед использованием пользовательского сопоставителя убедитесь, что полное имя целевого типа не содержит конфиденциальных или привилегированных сведений.
Примечания для тех, кто реализует этот метод
При реализации сопоставителя типов строка, возвращаемая ResolveTypeId(Type) методом, должна сопоставляться с тем же управляемым типом, когда строковое значение передается методу ResolveType(String) .
Конструкторы
| Имя | Описание |
|---|---|
| JavaScriptTypeResolver() |
Инициализирует новый экземпляр класса JavaScriptTypeResolver. |
Методы
| Имя | Описание |
|---|---|
| Equals(Object) |
Определяет, равен ли указанный объект текущему объекту. (Унаследовано от Object) |
| GetHashCode() |
Служит хэш-функцией по умолчанию. (Унаследовано от Object) |
| GetType() |
Возвращает Type текущего экземпляра. (Унаследовано от Object) |
| MemberwiseClone() |
Создает неглубокую копию текущей Object. (Унаследовано от Object) |
| ResolveType(String) |
При переопределении в производном классе возвращает Type объект, связанный с указанным именем типа. |
| ResolveTypeId(Type) |
При переопределении в производном классе возвращает имя типа для указанного Type объекта. |
| ToString() |
Возвращает строку, представляющую текущий объект. (Унаследовано от Object) |