0

次のタイプが与えられます

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のリストを用意することです。自分自身を検証するように求められているオブジェクトがリストにない場合は、そうでない場合に発生するランタイムエラーを回避できます。

どうすればいいですか?

乾杯、
ベリール

私が探していたコード

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

2 に答える 2

1

これを正しく理解している場合は、メソッドの明示的なインターフェイス実装を呼び出します。つまり、インターフェイスメソッドを実装し、クラスではなくインターフェイス自体にのみ表示されるメソッドを呼び出します。

これを行うには、最初に(with )のTypeオブジェクトを取得します。そのオブジェクトで、を呼び出してプロパティのインスタンスを取得します。IClassMappingtypeof(IClassMapping)GetPropertyPropertyInfoEntityType

PropertyInfo.GetValueこれで、インスタンスを呼び出すことでプロパティ値を取得できるようになりValidationDef<T>ます。

たとえば、次の方法を使用します。

Type GetEntityType(ValidationDef<T> def)
{
    PropertyInfo prop = typeof(IClassMapping).GetProperty("EntityType");
    return (Type)prop.GetValue(def, null);
}
于 2012-06-22T19:08:30.913 に答える
0

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:

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). Obviously, this may or may not be sufficient for your scenario.
  • BaseType returns the direct parent of the type being examined. 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.

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.

于 2012-06-22T20:20:53.583 に答える