Reputation: 103
I'd like to return the properties of a series of DbSet objects I have saved to a class using reflection, but in order to access this data in a single method I'd need to pass a variable as an accessor to return the properties of that object.
Currently I've managed to return the properties of all of the DbSet objects, but the code looks very DRY.
public DbSet<Foo> Foo {get;set;}
public DbSet<Bar> Bar {get;set;}
public List<string> GetPropertiesFoo()
{
DbContext client = new DbContext();
return client.Foo.GetType().GetProperties().Select(e => e.Name).ToList();
}
public List<string> GetPropertiesBar()
{
DbContext client = new DbContext();
return client.Bar.GetType().GetProperties().Select(e => e.Name).ToList();
}
My intention is to refactor this so that it accepts a DbSet name as an argument and returns a single list of properties, rather than a list of all properties.
Upvotes: 0
Views: 114
Reputation: 103
public List<Foo> GetFooFromBar(string bar)
{
return = typeof(FooContext)//a list of DbSets (DbSet<Foo>, DbSet<Bar>)
.GetProperties()
.Where(e => e.Name == bar)//Filter based on the name of DbSet entered
.GetType()//Get Type of the object returned (the DbSet with a matching name)
.GetGenericArguments()[0]//Get the first item in the array of PropertyInfo
.GetProperties()//Get a list of the properties of the DbSet within the Context
.ToList();
return bar;
}
Upvotes: 0
Reputation: 1036
I think you might be after something like this
public List<string> GetProperties(string model)
{
var property =
this.GetType()
.GetProperties()
.Where(p=>p.Name == model)
.FirstOrDefault();
if(property == null) return IEnumerable.Empty<string>().ToList();
return property
.PropertyType
.GetGenericArguments()[0]
.GetProperties()
.Select(p=>p.Name)
.ToList();
}
Upvotes: 0
Reputation: 119136
You are looking for something like this to do it all in one hit. Note this code is quite verbose so that each step can be explained:
// Make the method generic so we can use it on any context
public List<string> GetProperties<TContext>(string dbSetName = "")
where TContext : DbContext // Make sure we have a Dbcontext
{
var propertyNames = typeof(TContext)
// Get all properties of context
.GetProperties()
// Filter out so we only have DbSet<> types
.Where(pi => pi.PropertyType.IsGenericType &&
typeof(DbSet<>).IsAssignableFrom(pi.PropertyType.GetGenericTypeDefinition()))
// If a DbSet name has been specified, filter it out
.Where(pi => string.IsNullOrEmpty(dbSetName) || pi.Name == dbSetName)
// Get the generic type e.g. Foo
.Select(pi => pi.PropertyType.GetGenericArguments()[0])
// Get the individual properties of the entity types
.Select(t => t.GetProperties())
// Get all of the property names
.SelectMany(x => x.Select(pi => pi.Name));
return propertyNames.ToList();
}
And use it like this:
// All properties for all sets
var allProperties = GetProperties<MyContext>();
// Only properties for the Foo set
var fooProperties = GetProperties<MyContext>("Foo");
Upvotes: 1