Using Generics to return a literal string or from Dictionary<string, object>
I think I outsmarted myself this time. Feel free to edit the title also I could not think of a good one.
I am reading from a file and then in that file will be a string because its like an xml file. But in the file will be a literal value or a "command" to get the value from the workContainer
so
<Email>me@company.com</Email>
or
<Email>[? MyEmail ?]</Email>
What I wanted to do instead of writing ifs all over the place to put it in a generic function
so logic is
If Container command grab from container else grab string and convert to desired type
Its up to the user to ensure the file is ok and the type is correct
so another example is
so
<Answer>3</Answer>
or
<Answer>[? NumberOfSales ?]</Answer>
This is the procedure I started to work on
public class WorkContainer:Dictionary<string, object>
{
public T GetKeyValue<T>(string Parameter)
{
if (Parameter.StartsWith("[? "))开发者_如何学Go
{
string key = Parameter.Replace("[? ", "").Replace(" ?]", "");
if (this.ContainsKey(key))
{
return (T)this[key];
}
else
{
// may throw error for value types
return default(T);
}
}
else
{
// Does not Compile
if (typeof(T) is string)
{
return Parameter
}
// OR return (T)Parameter
}
}
}
The Call would be
mail.To = container.GetKeyValue<string>("me@company.com");
or
mail.To = container.GetKeyValue<string>("[? MyEmail ?]");
int answer = container.GetKeyValue<int>("3");
or
answer = container.GetKeyValue<int>("[? NumberOfSales ?]");
But it does not compile?
if(typeof(T) == typeof(string))
{
return (T)Parameter;
}
else
{
// convert the value to the appropriate type
}
The line
if (typeof(T) is string)
will always return false sine the typeof operator gives a Type object. You should replace it with
if (T is string)
In addition you should look at the Convert.ChangeType method. It may be of help here.
Use typeof(T) == typeof(string)
Change:
if (typeof(T) is string)
to:
if (typeof(T) == typeof(String))
The is operator is only valid on class instances. T is not actually an instance it is a type, therefor using is will not compile in your code because you need to compare 2 types. You can read more about it on msdn here.
So here is the answer I came up with, I am a little worried about boxing and unboxing but it works for now
public class WorkContainer:Dictionary<string, object>
{
public T GetKeyValue<T>(string Parameter)
{
if (Parameter.StartsWith("[? "))
{
string key = Parameter.Replace("[? ", "").Replace(" ?]", "");
if (this.ContainsKey(key))
{
if (typeof(T) == typeof(string) )
{
// Special Case for String, especially if the object is a class
// Take the ToString Method not implicit conversion
return (T)Convert.ChangeType(this[key].ToString(), typeof(T));
}
else
{
return (T)this[key];
}
}
else
{
return default(T);
}
}
else
{
return (T)Convert.ChangeType(Parameter, typeof(T));
}
}
}
精彩评论