Consider the following model (.NET 8, C# 12):
public partial interface IEntity
{
public long Id { get; set; }
}
public partial interface IEntity<TEntity>
where TEntity : class, IEntity, IEntity<TEntity>, new()
{
}
public partial class User: IEntity, IEntity<User>
{
public long Id { get; set; }
}
public partial class Currency: IEntity, IEntity<Currency>
{
public long Id { get; set; }
}
public partial class ApplicationDbContext: DbContext
{
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Currency> Currencies { get; set; }
//// TODO: Fix to get a list of DbSets.
//public static List<object> GetDbSets () => typeof(ApplicationDbContext)
// .GetProperties(BindingFlags.Instance | BindingFlags.Public)
// .Where(p => p.CanRead && p.CanWrite)
// .Where(p => p.GetGetMethod(nonPublic: false) != null)
// .Where(p => p.GetSetMethod(nonPublic: false) != null)
// .Where(p => p.PropertyType == typeof(DbSet<>))
// .Cast<object>()
// .ToList();
//// TODO: Fix to get a list of entities.
//public static List<Type> GetEntities () => typeof(ApplicationDbContext)
// .GetProperties(BindingFlags.Instance | BindingFlags.Public)
// .Where(p => p.CanRead && p.CanWrite)
// .Where(p => p.GetGetMethod(nonPublic: false) != null)
// .Where(p => p.GetSetMethod(nonPublic: false) != null)
// .Where(p => p.PropertyType.IsGenericType)
// .Where(p => p.PropertyType.Name.StartsWith(typeof(DbSet<>).Name))
// //.Where(p => p.PropertyType == typeof(DbSet<IEntity>))
// .Select(p => p.PropertyType.GetGenericArguments() [0])
// //.Cast<object>()
// .ToList();
public static List<Type> GetEntityTypesOrderedDelete () => new []
{
typeof(User),
typeof(Account),
typeof(Transaction),
typeof(AccountCategory),
typeof(Currency),
}
.ToList();
}
private static void Main ()
{
}
I want to get a list of properties List<System.Reflection.PropertyInfo> values using the following criteria:
- Properties must be instance, public, and virtual.
- Properties must inherit from
DbSet<IEntity<TEntity>>. - The generic
Dbsetproperties must have exactly one generic parameterIEntity<TEntity>. - The generic parameter
IEntity<TEntity>must have exactly one nested generic parameterTEntity. TEntitymust adhere to the generic type constraints enforced byIEntity<TEntity>.
The first two methods of the ApplicationDbContext class do not return anything. As a workaround, I took a hard-coded approach in the third method, which of course is not sustainable for production code.
The ideal solution would have the following signature:
public static ReadOnlyCollection<PropertyInfo> GetApplicationDbContextDbSets ()
{
var properties = typeof(ApplicationDbContext)
.GetProperties();
return (properties.AsReadOnly());
}
I must be missing something or using the APIs incorrectly.
Any advice would be appreciated.
This filtering should fulfill you requirements:
In production code I would write this as full for each loop instead of LINQ to have better debuggability and less duplicated expressions.