简体   繁体   English

使用反射从接口获取类型

[英]use reflection to get type from an interface

Given the following types 鉴于以下类型

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

At configuration time I know all of the ValidationDefinitions; 在配置时,我知道所有的ValidationDefinitions。 "MyTestDummyClassValidationDef " above is an example of such a definition. 上面的“ MyTestDummyClassValidationDef”就是这样一个定义的例子。

If you follow the inheritance / implementation trail, at the end is an EntityType that is exposed by IClassMapping. 如果遵循继承/实现轨迹,则最后是IClassMapping公开的EntityType。

As part of my validation infrastructure, various objects may be asked to validate themselves. 作为我的验证基础结构的一部分,可能会要求各种对象进行自我验证。 The objects may or may not have a ValidationDef defined for them, either because validation doesn't apply fo that object or the definition hasn't been written yet. 这些对象可能有也可能没有为其定义ValidationDef,这是因为验证不适用于该对象,或者尚未写入定义。 If an object is asked to validate itself and there is no definition then a runtime error will occur. 如果要求对象进行自我验证且没有定义,则将发生运行时错误。

SO, what I am trying to is have a list of EntityTypes that I can use to check at runtime. 所以,我想要做的是有一个EntityTypes列表,我可以在运行时检查它。 If the object being asked to validate itself is not on the list then I can avoid the runtime error that would otherwise occur. 如果要求对象进行自我验证的对象不在列表中,则可以避免发生运行时错误。

How might I do that? 我该怎么办?

Cheers, 干杯,
Berryl 贝里

the code I was looking for 我正在寻找的代码

public EntityValidator(ValidatorEngine validatorEngine, IEnumerable<Type> defTypes) {

ValidationDefs = new List<Type>();
foreach (var type in defTypes) 
{
    if (type.BaseType.GetGenericTypeDefinition() != typeof(ValidationDef<>)) continue;

    var mappingSource = (IMappingSource) Activator.CreateInstance(type);
    var entityType = mappingSource.GetMapping().EntityType;
    ValidationDefs.Add(entityType);
}

If I understand this correctly, you want to call an explicit interface implementation of a method, ie a method that implements an interface method and that is only visible in the interface itself, not in the class. 如果我正确理解这一点,则需要调用方法的显式接口实现,即,一种实现接口方法的方法,该方法仅在接口本身中可见,而在类中不可见。

In order to do so, first retrieve the Type object for IClassMapping (with typeof(IClassMapping) ). 为此,请首先检索IClassMappingType对象(带有typeof(IClassMapping) )。 On that object, call GetProperty to retrieve a PropertyInfo instance for the EntityType property. 在该对象上,调用GetProperty来检索EntityType属性的PropertyInfo实例。

You should then be able to retrieve the property value by invoking PropertyInfo.GetValue on your ValidationDef<T> instance. 然后,您应该能够通过在ValidationDef<T>实例上调用PropertyInfo.GetValue来检索属性值。

Use, for example, this method: 使用例如以下方法:

Type GetEntityType(ValidationDef<T> def)
{
    PropertyInfo prop = typeof(IClassMapping).GetProperty("EntityType");
    return (Type)prop.GetValue(def, null);
}

Ok, after clarification (see comments to the question), here is the way to find all implementations of ValidationDef in an assembly and create a list of values of their EntityType properties: 好的,在澄清之后(请参阅问题注释),这是在程序集中查找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;
}

Few points to note here: 这里要注意的几点:

  • Types in the current assembly are being examined ( Assembly.GetExecutingAssembly ). 正在检查当前程序集中的类型( Assembly.GetExecutingAssembly )。 Obviously, this may or may not be sufficient for your scenario. 显然,这可能足以满足您的情况。
  • BaseType returns the direct parent of the type being examined. BaseType返回所检查类型的直接父级。 Again, you may want to examine the type hierarchy a bit further up the inheritance chain. 同样,您可能想在继承链的更深处检查类型层次结构。
  • It is assumed that all examined types have a parameterless constructor. 假定所有检查的类型都具有无参数构造函数。 Otherwise, Activator.CreateInstance bit won't work. 否则, Activator.CreateInstance位将不起作用。

Although it is certainly possible to do what you ask, I would like to strongly emphasize that it is very likely that there is much, much simpler solution to your validation needs. 尽管当然可以按照您的要求进行操作,但我想特别强调一下,很可能有很多非常简单的解决方案可以满足您的验证需求。 From what you've told us of your solution, it is obvious that it has a few serious flaws: 根据您对解决方案的了解,很明显它存在一些严重的缺陷:

  • How is it possible that you can invoke validation on objects that cannot be validated? 您怎么可能对无法验证的对象调用验证? I think that this is the root of all your sorrows. 我认为这是所有悲伤的根源。
  • Your inheritance hierarchy is far too complex and hard to understand. 您的继承层次结构太复杂且难以理解。 Why do you need so many interfaces? 为什么需要这么多接口?

Perhaps try to create a separate question detailing your validation needs. 也许尝试创建一个单独的问题,详细说明您的验证需求。 I am sure that a simpler solution can be found. 我相信可以找到一个更简单的解决方案。

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

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