繁体   English   中英

如何确定 class 实现了具有自引用通用约束的特定接口?

[英]How to determine that a class implements a specific interface with self-referencing, generic constraints?

我有一个DbContext派生的 class 并希望获取其通用参数Entity符合以下条件的所有DbSet<Entity>属性的列表:

  • Entity不得从 class 继承。
  • Entity必须实现接口IEntity
  • Entity必须实现接口IEntity<TEntity> ,其中TEntity具有以下约束:

where TEntity: class, IEntity, IEntity<TEntity>, new()

下面代码中的倒数第二行尝试这样做但失败了。 此外,我不知道如何在运行时表达约束检查。

属性DbSet<Employee>应该通过检查,而DbSet<Department>不应该。

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);
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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