C# 使用反射从接口获取类型

C# 使用反射从接口获取类型,c#,.net,reflection,C#,.net,Reflection,鉴于以下类型 private class MyTestDummyClassValidationDef : ValidationDef<MyTestDummyClass> { ... } public class ValidationDef<T> : IValidationDefinition<T>, IConstraintAggregator, IMappingSource where T : class        { 

鉴于以下类型

private class MyTestDummyClassValidationDef : ValidationDef<MyTestDummyClass>
    {
        ...
    }

public class ValidationDef<T> : IValidationDefinition<T>, IConstraintAggregator, IMappingSource where T : class        
{        }

public interface IMappingSource
{
    IClassMapping GetMapping();
}

public interface IClassMapping
{
    Type EntityType { get; }
    ...
}
私有类MyTestDummyClassValidationDef:ValidationDef
{
...
}
公共类ValidationDef:IValidationDefinition、IConstraintAggregator、IMappingSource其中T:class
{        }
公共接口IMappingSource
{
IClassMapping GetMapping();
}
公共接口IClassMapping
{
类型EntityType{get;}
...
}
在配置时,我知道所有ValidationDefinitions;上面的“MyTestDummyClassValidationDef”就是这样一个定义的示例

如果遵循继承/实现轨迹,那么最后是一个EntityType,它由IClassMapping公开

作为验证基础结构的一部分,可能会要求各种对象进行自我验证。对象可能有也可能没有为其定义ValidationDef,这可能是因为验证不适用于该对象,或者定义尚未编写。如果要求对象验证自身,但没有定义,则会发生运行时错误

所以,我试图得到一个EntityTypes列表,我可以在运行时使用它来检查。如果要求验证自身的对象不在列表中,那么我可以避免否则会发生的运行时错误

我该怎么做

干杯,
贝里尔

我正在寻找的代码 公共实体验证器(验证器引擎验证器引擎,IEnumerable defTypes){ ValidationDefs=新列表(); foreach(defTypes中的变量类型) { 如果(type.BaseType.GetGenericTypeDefinition()!=typeof(ValidationDef))继续; var mappingSource=(IMappingSource)Activator.CreateInstance(类型); var entityType=mappingSource.GetMapping().entityType; ValidationDefs.Add(entityType); }
如果我理解正确,您希望调用方法的显式接口实现,即实现接口方法且仅在接口本身中可见而在类中不可见的方法

为此,首先检索
IClassMapping
(使用
typeof(IClassMapping)
)的
Type
对象。在该对象上,调用
GetProperty
检索
EntityType
属性的
PropertyInfo
实例

然后,您应该能够通过调用
ValidationDef
实例上的
PropertyInfo.GetValue
来检索属性值

例如,使用以下方法:

Type GetEntityType(ValidationDef<T> def)
{
    PropertyInfo prop = typeof(IClassMapping).GetProperty("EntityType");
    return (Type)prop.GetValue(def, null);
}
Type GetEntityType(ValidationDef)
{
PropertyInfo prop=typeof(IClassMapping).GetProperty(“EntityType”);
返回(类型)prop.GetValue(def,null);
}
好的,澄清之后(请参见问题的注释),下面是在程序集中查找ValidationDef的所有实现并创建其EntityType属性值列表的方法:

List<Type> entityTypes = new List<Type>();

foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
{
    if (InheritsFromValidationDef(type))
    {
        IMappingSource mappingSource = (IMappingSource)Activator.CreateInstance(type);
        entityTypes.Add(mappingSource.GetMapping().EntityType);
    }
}

private static bool InheritsFromValidationDef(Type type)
{
    Type baseType = type.BaseType;
    bool result = baseType != null && 
                  baseType.IsGenericType &&
                  baseType.GetGenericTypeDefinition() == typeof(ValidationDef<>);
    return result;
}
List entityTypes=new List();
foreach(在Assembly.getExecutionGassembly().GetTypes()中键入类型)
{
if(继承自验证定义(类型))
{
IMappingSource mappingSource=(IMappingSource)Activator.CreateInstance(类型);
添加(mappingSource.GetMapping().EntityType);
}
}
私有静态bool InheritsFromValidationDef(类型)
{
类型baseType=Type.baseType;
bool result=baseType!=null&&
baseType.IsGenericType&&
baseType.GetGenericTypeDefinition()==typeof(ValidationDef);
返回结果;
}
这里需要注意的几点:

  • 正在检查当前程序集中的类型(
    assembly.getExecutionGassembly
    )。显然,这对于您的场景来说可能足够,也可能不够
  • BaseType
    返回被检查类型的直接父级。同样,您可能希望在继承链的更上层检查类型层次结构
  • 假设所有检查的类型都有一个无参数构造函数。否则,
    Activator.CreateInstance
    bit将无法工作
尽管可以按照您的要求执行,但我想强烈强调,很可能存在非常简单的解决方案来满足您的验证需求。从您对我们介绍的解决方案来看,它显然存在一些严重缺陷:

  • 你怎么可能对无法验证的对象调用验证?我认为这是你所有烦恼的根源
  • 您的继承层次结构太复杂,难以理解。为什么需要这么多接口

也许可以尝试创建一个单独的问题,详细说明您的验证需求。我相信可以找到一个更简单的解决方案。

您可以再详细说明一点吗?
ValidationDef:IValidationDefinition
——保持一致;选择缩写或不缩写。不要同时选择两者。已经阅读并重新阅读您的问题将近10分钟了现在我还是不明白你在问什么。请尝试重新表述它。@KirkWoll。该类实际上来自开源的NHibernate验证器项目,在任何情况下都与此练习无关。我想作者会很乐意听到你的代码审查:——)@Berryl所以在运行时,你希望能够o查找
ValidationDef
的所有实现(可能在某些特定程序集中)并创建其
EntityType
属性的值列表?对吗?如果为该类型设置了任何类型参数,则
BaseType
比较将返回
false
。关闭的泛型类型不会从其泛型类型定义继承(可以使用
type.GetGenericTypeDefinition
检索)。此外,如果继承关系是间接的,您可能希望使用
Type.IsSubclassOf
方法,而不是直接与
Type.BaseType
@Nikola Anusev进行相等比较。O.R.Mapper对代码中的错误非常正确;请更正它,以便我可以奖励
List<Type> entityTypes = new List<Type>();

foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
{
    if (InheritsFromValidationDef(type))
    {
        IMappingSource mappingSource = (IMappingSource)Activator.CreateInstance(type);
        entityTypes.Add(mappingSource.GetMapping().EntityType);
    }
}

private static bool InheritsFromValidationDef(Type type)
{
    Type baseType = type.BaseType;
    bool result = baseType != null && 
                  baseType.IsGenericType &&
                  baseType.GetGenericTypeDefinition() == typeof(ValidationDef<>);
    return result;
}