简体   繁体   中英

c# generics how to cast return type?

i have a dictionary

var dictionary = new Dictionary<string,string>{{"name","Smith"},{"age","20"}};

and i want to map it's values to a class

class Person{ 
public string Name {get;set;} 
public string Age {get;set;}
}

i tried to do it in this way

public T Map<T>(Dictionary<string, object> row) 
{
      var p= new Person();
      if (row.ContainsKey("name")) Person.Name= row["name"];
      if (row.ContainsKey("age")) Person.Age= row["age"];
      return (T) p;
}

and the problem is that i fail at return type, i dont know how to cast T to class Person. any ideas ? Thanks.

The issue is with this line:

var p= new Person();

You are trying to return a Person type, though T can be anything .

You need to add a generic type constraint to the class, only allowing T to be a Person - though that wouldn't be very useful.

But in your case, generics are not even needed:

public Person Map(Dictionary<string, string> row) 
{
      var p= new Person();
      if (row.ContainsKey("name")) Person.Name= row["name"];
      if (row.ContainsKey("age")) Person.Age= row["age"];
      return p;
}

T is just a type. You wouldn't be casting it to anything. If you had an instance of T, you would have (Person)T.

You can also do: where T: Person assuming your question is just worded in reverse.

If you had a dictionary of the form:

new Dictionary<string,string>{{"Smith", "20"},{"Paul","44"}}

You can do this easily with LINQ. Something like:

dictionary
    .Select(k=>new Person()
        {
            Name=k.Key,
            Age=k.Value
        })
    .ToList();

With the dictionary you have, you'd have to do something like:

public Person GetPersonFromDictionary(Dictionary<string,string> dictionary)
{
    var myPerson = new Person()
    {
        Name=dictionary[name],
        Age=dictionary[age]
    }
    return myPerson;
}

Assuming you were guaranteed the dictionary had the values you needed. I don't see any need to involve generics here.

Either:

public Person Map(Dictionary<string, object> row) 
{
      var p= new Person();
      if (row.ContainsKey("name")) Person.Name= row["name"];
      if (row.ContainsKey("age")) Person.Age= row["age"];
      return p;
}

Or:

public T Map<T>(Dictionary<string, object> row) 
 where T : Person
{
      var p= new Person();
      if (row.ContainsKey("name")) Person.Name= row["name"];
      if (row.ContainsKey("age")) Person.Age= row["age"];
      return (T) p;
}

Or:

public T Map<T>(Dictionary<string, object> row) 
 where T : Person, new ()
{
      var p= new T();
      if (row.ContainsKey("name")) Person.Name= row["name"];
      if (row.ContainsKey("age")) Person.Age= row["age"];
      return p;
}

You can use reflection to populate the properties:

 public static T Map<T>(Dictionary<string, string> dictionary) where T : class, new()
    {
        var obj = new T();
        var properties = typeof(T).GetProperties();

        foreach (var item in dictionary)
        {
            var prop = properties.FirstOrDefault(p => p.Name.Equals(item.Key, StringComparison.InvariantCultureIgnoreCase));
            if (prop != null)
                prop.SetValue(obj, item.Value, null);
        }

        return obj;
    }

...

 var dictionary = new Dictionary<string, string> { { "name", "Smith" }, { "age", "20" } };
 Person o = Map<Person>(dictionary);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM