"Store" a type parameter for later use in C#?
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>("Nu开发者_如何学GomberOfFoos",
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.
Something like
public void Set<T>(Tuple<string,T> key, T value) { /* stuff */ }
might do it
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.
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.
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.
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.
I don't think you need to deal with Type
s 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.
精彩评论