Каков наилучший способ представить типобезопасный пакет свойств в классе? - PullRequest
11 голосов
/ 20 декабря 2011

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

5 голосов
/ 21 декабря 2011

Использование нескольких словарей просто не выглядит красиво :) Но может работать в некоторых сценариях.

Если вы абсолютно уверены, что строки достаточно для всех - используйте строки.Но если какой-то другой код потребуется для его анализа - это будет дорого.

Если вам нужно действительно простое простое решение - просто используйте объекты.Несмотря на то, что в нем будут введены блокировка / распаковка для типов значений (забудьте об этом, если вы не оперируете тысячами объектов), и вы потеряете информацию о типах для значений, это решение все равно может работать очень хорошо.

Также вы можетерассмотреть возможность введения промежуточного класса для значения.Что-то вроде

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 в строковой переменной и т. Д., Т. Е. Иметь отдельную переменную для каждого типа) итогда вы можете избежать преобразования типов.Также вы можете обернуть свой словарь в другой класс, добавить несколько полезных средств доступа и сделать его более привлекательным.Я не знаю, как это вписывается в вашу инфраструктуру.

0 голосов
/ 20 декабря 2011

Как насчет того, чтобы сделать ваш класс 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, но клиент по крайней мере будет иметь некоторую безопасность типов на уровне объекта ответа.

...