使用反射从接口获取类型

时间:2012-06-22 18:54:41

标签: c# .net reflection

鉴于以下类型

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

在配置时我知道所有的ValidationDefinitions;上面的“MyTestDummyClassValidationDef”就是这种定义的一个例子。

如果您遵循继承/实现跟踪,最后是IClassMapping公开的EntityType。

作为验证基础架构的一部分,可能会要求各种对象自行验证。对象可能有也可能没有为它们定义ValidationDef,因为验证不适用于该对象或尚未编写定义。如果要求对象验证自身并且没有定义,则会发生运行时错误。

所以,我想要的是有一个EntityTypes列表,我可以在运行时检查它。如果要求验证的对象不在列表中,那么我可以避免发生的运行时错误。

我该怎么做?

干杯,
Berryl

我正在寻找的代码

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

2 个答案:

答案 0 :(得分:1)

如果我理解正确,你想要调用一个方法的显式接口实现,即一个实现接口方法的方法,它只在接口本身可见,而不是在类中。

要执行此操作,请先检索Type的{​​{1}}对象(IClassMapping)。在该对象上,调用typeof(IClassMapping)以检索GetProperty属性的PropertyInfo实例。

然后,您应该可以通过在EntityType实例上调用PropertyInfo.GetValue来检索属性值。

例如,使用此方法:

ValidationDef<T>

答案 1 :(得分:0)

好的,在澄清之后(参见问题的评论),这里是在程序集中查找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;
}

这里有几点需要注意:

  • 正在检查当前程序集中的类型(Assembly.GetExecutingAssembly)。显然,这可能适用于您的情况,也可能不够。
  • BaseType返回被检查类型的直接父级。同样,您可能希望在继承链上进一步检查类型层次结构。
  • 假设所有检查的类型都具有无参数构造函数。否则,Activator.CreateInstance位将不起作用。

虽然您可以按照自己的要求行事,但我希望强烈强调您的验证很可能会有更多 更简单的解决方案需要。从你告诉我们你的解决方案来看,很明显它有一些严重的缺陷:

  • 您如何才能对无法验证的对象调用验证?我认为这是你所有悲伤的根源。
  • 您的继承层次结构过于复杂且难以理解。为什么需要这么多接口?

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