I have a DbContext
-derived class and want to get a list of all DbSet<Entity>
properties whose generic argument Entity
matches the following criteria:
Entity
must not inherit from a class.Entity
must implement the interfaceIEntity
.Entity
must implement the interfaceIEntity<TEntity>
whereTEntity
has the following constraints:
where TEntity : class, IEntity, IEntity<TEntity>, new()
The second-last line in the code below attempts to do that but fails. Furthermore, I do not know how to express constraint checks at runtime.
The property DbSet<Employee>
should pass the check whereas DbSet<Department>
should not.
namespace DomainBuilder
{
internal static class Program
{
private static void Main (string [] args)
{
var dbSetProperties = typeof (DomainBuilder.DomainBuilderContext)
.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.Name.StartsWith (nameof (DbSet<DomainBuilder.IEntity>))))
.Where (p => (p.PropertyType.IsGenericType))
.Where (p => (p.PropertyType.GenericTypeArguments.Length == 1))
.ToList();
foreach (var dbSetProperty in dbSetProperties)
{
Console.WriteLine ($@"DbSet<{dbSetProperty.PropertyType.GenericTypeArguments [0].Name}>: {DomainBuilder.DomainBuilderContext.ImplementsIEntityGenericWithConstraints (dbSetProperty)}.");
}
}
}
public interface IEntity
{
public long Id { get; set; }
public DateTime DateTimeCreated { get; set; }
public DateTime DateTimeModified { get; set; }
}
public partial interface IEntity<TEntity>: IEntity
where TEntity : class, IEntity, IEntity<TEntity>, new()
{ }
public partial class Employee: IEntity<Employee>
{
public long Id { get; set; }
public DateTime DateTimeCreated { get; set; }
public DateTime DateTimeModified { get; set; }
public long? DepartmentId { get; set; }
public Department? Department { get; set; }
}
public partial class Department: IEntity
{
public long Id { get; set; }
public DateTime DateTimeCreated { get; set; }
public DateTime DateTimeModified { get; set; }
public string Name { get; set; } = "";
}
public partial class DomainBuilderContext: DbContext
{
public virtual DbSet<Employee>? Employees { get; set; }
public virtual DbSet<Department>? Departments { get; set; }
public static bool ImplementsIEntityGenericWithConstraints (PropertyInfo dbSetProperty)
{
var typeDbSet = dbSetProperty.PropertyType; // DbSet<Employee>.
var typeEntity = typeDbSet.GenericTypeArguments [0]; // Employee.
if (typeEntity.BaseType != typeof (object)) { return (false); }
var interfaces = typeEntity.GetInterfaces();
// Works fine.
var isIEntity = interfaces.Any (i => i == typeof (IEntity));
// How to ensure that [typeEntity] implements [IEntity<TEntity>]
// where TEntity: class, IEntity, IEntity<TEntity>, new().
var isIEntityGeneric = interfaces.Any (i => i == typeof (IEntity<>));
return (isIEntity && isIEntityGeneric);
}
}
}
Aucun commentaire:
Enregistrer un commentaire