Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to represent a type-safe property bag in a class?

I have a 3rd party application that provides an object with many "attributes", which are simply pairs of (string) keys and values. The value types can be either strings, DateTime, Int32 or Int64.

I need to create my own class to represent this object, in a convenient way. I'm creating a WCF service that provides this object to clients, so I need it to be very easy and clean.

The keys of the attributes will be presented as an Enum for the clients (to hide the information of the specific key strings of the 3rd party application). However, I'm not sure how to represent the values. Here are some of the options:

Option 1: Have different collection per attribute values, seems ugly but will be very easy for clients to use

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; }

Option 2: Convert all of the attributes to strings

public class MyObject
{
    public Dictionary<MyAttributeKeysEnum, string> MyAttributes { get; set; }

    public string Name { get; set; }
    public string Id{ get; set; }

Option 3: Keep them as objects, let the clients bother with casting and converting

public class MyObject
{
    public Dictionary<MyAttributeKeysEnum, object> MyAttributes { get; set; }

    public string Name { get; set; }
    public string Id{ get; set; }
like image 789
yellowblood Avatar asked Dec 20 '11 13:12

yellowblood


1 Answers

Using several dictionaries just doesn't look nice :) But might work in some scenarios.

If you are absolutely sure that string is enough for all - go with strings. But if some other code would need to parse it - that's going to be expensive.

If you want a really simple straightforward solution - just go with objects. Even though it would introduce boxing/unboxing for value types (forget it if you don't operate thousands of objects) and you'd lose type information on values this solution might still work just fine.

Also you might consider introducing an intermediate class for a value. Something like

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; }
    // ...
}

Internally you could store your value in a variable of the original type (int in an int variable, string in a string variable, etc., i.e. have a separate variable for each type) and then you can avoid type conversion. Also you could wrap your dictionary in another class, add some usefull accessors and make it look nicer. I don't know how does this fit into your infrastructure though.

like image 114
ttil Avatar answered Oct 24 '22 11:10

ttil