Каков наилучший способ представить типобезопасный пакет свойств в классе?

У меня есть стороннее приложение, которое предоставляет объект со многими "атрибутами", которые являются просто парами (строковых) ключей и значений. Типы значений могут быть строками, 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, но клиент, по крайней мере, будет иметь некоторую безопасность типов на уровне объекта ответа.

Другие вопросы по тегам