Array Indexing Properties of A Class
I have a class that has several properties:
class Person
{
string Name;
int Age;
DateTime BirthDate;
}
Then I have a sort of wrapper class with a List<Person>
. Within this wrapper class I want to be able to do something like Wrapper["Name"]
that returns a new List<string>
using .Select(x=>x.Name)
.
How do I create a wrapper class around an IEnumerable that supports mapping a string to the Property name? Something like the pseudo code below, but obviously it doesn't work. I'm 99.9% sure the solution will have to use Reflection and thats fine.
class Wrapper
{
List<Person> PersonList;
List<dynamic> this[string Column]
{
return PersonList.Select(x => x.[Column]).ToList();
}
}
This may not seem like a good design, but its a fix to eventually e开发者_运维技巧nable the correct design from .NET 2.0 days. As I have it right now, the data is stored in Columns, so there is actually a List of Lists within my class right now.
Using the above example there would be three ILists (with a string Title) Name, Age, and Birthdate.
Everything is currently predicated on addressing the columns by their "string" name. I'm trying to convert the data structure to row based with an IEnumberable interface to allow Linq eventually while still maintaining the functionality of my current code.
Is converting the code to a Row based IEnumberable a good idea?
Something like this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var test = new Wrapper();
var test2 = test.GetValue<String>("Name");
foreach (var val in test2)
{
Console.WriteLine(val);
}
}
}
}
class Person
{
public string Name;
int Age;
DateTime BirthDate;
}
public class Wrapper
{
List<Person> PersonList = new List<Person> { new Person() { Name = "rob" }, new Person() { Name = "Test" } };
public List<Object> GetValue(String column)
{
return GetValue<Object>(column);
}
public List<T> GetValue<T>(String column)
{
if (PersonList.Count > 0)
{
var field = PersonList.FirstOrDefault().GetType().GetField(column);
if (field == null)
return null;
return PersonList.Select(person => (T) field.GetValue(person)).ToList();
}
return null;
}
}
Edit: Didn't see you're required to access by string name
I would prefer a design like this instead
class Wrapper
{
List<Person> PersonList;
List<T> GetColumns<T>(Func<Person, T> func)
{
return PersonList.Select(p => func(p)).ToList();
}
}
This makes the column access strongly typed and you can get all the names like this
IList<string> names = wrapper.GetColumns(p => p.Name);
IList<DateTime> birthDates = wrapper.GetColumns(p => p.BirthDate);
You can use DictionaryBase to implement your Wrapper. This is a very basic wrapper class which only returns a list, care should be taken to append all the persons with same name to be appended in Wrapper[name].
class Wrapper : DictionaryBase
{
public List<Person> this[string key]
{
get
{
return this[key];
}
}
}
精彩评论