views:

95

answers:

6

I'm creating a Settings object in my app, used for storing user-defined settings and whatnot. I plan on using various datatypes for my setting fields (ints, strings, enums, anything Serializable, really).

I'd also like, if possible, a type-safe way to set any of the settings. My proposed method would be doing something like this:

Tuple<string, Type> SettingName = new Tuple<string, Type>("NumberOfFoos",
                                                          typeof(**TYPE**));
public void Set(Tuple<string, Type> key, **TYPE** value) { /* Stuff */ }

The Tuple would effectively be the "setting" that the user would push a value to, and would consist of the key for that setting as well as the type of that setting. What I'm wondering is if there's any way to have the compiler enforce that, in the Set() method, the type of value is of the same type as the type object saved in the tuple passed to Set()? Is the way I proposed even possible? Thanks!

EDIT: I thought of some more things I should clarify.

1) This is intended to be a static class, so I won't be able to serialize the whole class, only members in it. Therefore, I'd really like to not have to deal with a serialization for each field. I was planning on storing all the setting values in a Dictionary<string, **TYPE**> and serializing that.

2) The Tuple definitions are meant to be constant and static. I'm really treating them as more of a typedef-type thing (I really should make my own SettingKey struct), which the user passes to Set to indicate what field they are changing. The Type parameter is meant to enforce the the value parameter is of the specified type.

+2  A: 

Something like

public void Set<T>(Tuple<string,T> key, T value) { /* stuff */ }

might do it

MrDosu
Actually, this ended up working out pretty well, thanks!
Mark LeMoine
A: 

Well, if you did something like Set<T>(Tuple<string, T>, T value), you'd get what you're after for setting. And I think the compiler could infer the T in Set<T>() at usage, so you would have to write it.

But your Get<T>(), you'd have to specify the type you expected to get back.

uosɐſ
+2  A: 

It's better to get rid of the tuple, and use a generic method:

public void Set<T>(string key, T value);

That way, you can specify the type at compile-time

Set<string>("MyStringKey", "foo");
Set<int>("MyIntKey", 1);

or the compiler can infer it for you:

Set("MyStringKey", "foo");
Set("MyIntKey", 1);

and in Set, you can use typeof(T) to get the Type object you would have passed in.

thecoop
The thing is though, I'd want to enforce that the value param is of the type I've specified in the tuple.
Mark LeMoine
but you don't _need_ the tuple, the compiler can work out the type automatically without it, depending on the type of the `value` parameter
thecoop
A: 
public class Foo
{
  Tuple<string, Type> SettingName = new Tuple<string, Type>("NumberOfFoos",
                                                          typeof(**TYPE**));
  public void Set(Tuple<string, Type> key, object value) 
  {
    if(value.GetType() != SettingsName.Value)
      throw new ArgumentException("value");
  }
}

You would be better of using generics like in the other answers though.

Femaref
+2  A: 

Why not simply add strongly typed properties to your settings object? e.g. public int NumberOfFoos {get {} set {...}} and in the getter and setter call your common serialization and deserialization code.

If you do this your settings object isn't exposing how it works internally and you have full intellisense support on it.

Hightechrider
Well, I also want to avoid having a private numberOfFoos field and a separate NumberOfFoos property, for each of my 60 or so setting fields. I was planning on using a Dictionary to store all the settings, based on the key. I'd have to cast when retrieving values, but that's why I wanted to use Types like this.
Mark LeMoine
You could make them all auto properties, e.g. `public int NumberOfFoos {get; set;}` add for serialization you could add a `[DataContract]` to the class and a `[DataMember]` attribute to each property making it a one-liner to serialize the whole settings class to XML or JSON etc. That would be much cleaner overall.
Hightechrider
A: 

I don't think you need to deal with Types at all. Would something like this be good enough?

class Settings {
  public static int Foo { 
    get { return (int)_map["Foo"]; }
    set { _map["Foo"] = value; }
  }
  public static string Bar {
    get { return (string)_map["Foo"]; }
    set { _map["Foo"] = value; }
  }
  // ...
  private static Dictionary<string, object> _map = 
    new Dictionary<string, object>();
}

You'd then serialize the dictionary. You could even use some code-generation to create this class.

Jordão