Каков наилучший способ представить типобезопасный пакет свойств в классе?
У меня есть стороннее приложение, которое предоставляет объект со многими "атрибутами", которые являются просто парами (строковых) ключей и значений. Типы значений могут быть строками, DateTime, Int32 или Int64.
Мне нужно создать свой собственный класс для удобного представления этого объекта. Я создаю сервис WCF, который предоставляет этот объект клиентам, поэтому мне нужно, чтобы он был очень простым и чистым.
Ключи атрибутов будут представлены в виде Enum для клиентов (чтобы скрыть информацию о конкретных строках ключей стороннего приложения). Тем не менее, я не уверен, как представлять значения. Вот некоторые из вариантов:
Вариант 1: иметь разные коллекции для каждого значения атрибута, кажется уродливым, но его будет очень легко использовать клиентам
public class MyObject
{
public Dictionary<MyTextAttributeKeysEnum, string> TextAttributes { get; set; }
public Dictionary<MyDateAttributeKeysEnum, DateTime> DateAttributes { get; set; }
public Dictionary<MyNumAttributeKeysEnum, long> NumericAttributes { get; set; }
public string Name { get; set; }
public string Id{ get; set; }
Вариант 2: преобразовать все атрибуты в строки
public class MyObject
{
public Dictionary<MyAttributeKeysEnum, string> MyAttributes { get; set; }
public string Name { get; set; }
public string Id{ get; set; }
Вариант 3: Храните их как объекты, пусть клиенты возятся с приведением и преобразованием
public class MyObject
{
public Dictionary<MyAttributeKeysEnum, object> MyAttributes { get; set; }
public string Name { get; set; }
public string Id{ get; set; }
2 ответа
Использование нескольких словарей выглядит не очень красиво:) Но может работать в некоторых сценариях.
Если вы абсолютно уверены, что строки достаточно для всех - идите со строками. Но если какой-то другой код потребуется для его анализа - это будет дорого.
Если вы хотите действительно простое простое решение - просто используйте объекты. Несмотря на то, что он вводит / распаковывает для типов значений (забудьте об этом, если вы не работаете с тысячами объектов), и вы потеряете информацию о типах для значений, это решение может все еще работать очень хорошо.
Также вы можете рассмотреть возможность введения промежуточного класса для значения. Что-то вроде
public Dictionary<MyAttributeKeysEnum, PropertyBagValue> MyAttributes { get; set; }
public class PropertyBagValue
{
public object AsObject { get; set; }
public string AsString { get; set; }
public int AsInt { get; set; }
// ...
}
Внутренне вы можете сохранить свое значение в переменной исходного типа (int в переменной int, string в строковой переменной и т. Д., Т. Е. Иметь отдельную переменную для каждого типа), а затем вы можете избежать преобразования типов. Также вы можете обернуть свой словарь в другой класс, добавить несколько полезных средств доступа и сделать его более привлекательным. Я не знаю, как это вписывается в вашу инфраструктуру.
Как насчет того, чтобы сделать класс DataContract абстрактным и обеспечить словари с типами, которые вам нужны в производных классах:
[DataContract]
[KnownType(typeof(My3dPartyObjectString))]
[KnownType(typeof(My3dPartyObjectInt64))]
public abstract class My3dPartyObjectBase
{
// some common properties
}
[DataContract]
public class My3dPartyObjectString : My3dPartyObjectBase
{
public Dictionary<3PAttributeKeysEnum, string> MyStringAttributes { get; set; }
}
[DataContract]
public class My3dPartyObjectInt64 : My3dPartyObjectBase
{
public Dictionary<3PAttributeKeysEnum, long> MyStringAttributes { get; set; }
}
Затем клиент должен будет проанализировать реальный тип возвращаемого объекта и получить коллекцию атрибутов на основе типа. Это было бы близко к вашему варианту 3d, но клиент, по крайней мере, будет иметь некоторую безопасность типов на уровне объекта ответа.