Я немного боролся с каким-то кодом отражения, который я хотя бы был простым. По сути, у меня есть интерфейс, который определяет метод. Затем у меня есть абстрактный класс, который обеспечивает базовую реализацию этого метода.
Конкретные классы могут содержать вложенные экземпляры других классов, которые также могут быть производными от того же базового класса. Это можно проиллюстрировать на следующем примере:
using System.Linq;
public interface ISampleObject
{
bool IsValid();
}
public abstract class SampleObjectBase : ISampleObject
{
public bool IsValid()
{
var returnValue = true;
// Self-validation sets the return value.
var childProperties = this.GetType().GetProperties().Where(pi => typeof(ISampleObject).IsAssignableFrom(pi.PropertyType));
foreach (var childProperty in childProperties)
{
// var childInstance = ????; // Need the actual *existing* instance property, cast to ISampleObject.
// if (childInstance.IsValid() != true)
// {
// returnValue = false;
// }
}
return returnValue;
}
}
public sealed class InnerSampleObject : SampleObjectBase
{
}
public sealed class OuterSampleObject : SampleObjectBase
{
public InnerSampleObject DerivedSampleObject { get; set; }
}
Моя проблема в том, что в закомментированном коде для SampleObjectBase я не могу получить конкретный экземпляр соответствующего значения PropertyInfo. Если я смотрю на объект PropertyInfo в цикле, я вижу, что тип является правильным, но я не могу найти способ прямого доступа к экземпляру, который уже существует в реализации. Итак, при выполнении, например, OuterSampleObject.IsValid (), код находит PropertyInfo для InnerSampleObject, как и ожидалось. Я хочу выполнить InnerSampleObject.IsValid ().
Я пробовал (несколько вариантов):
var childIsValid = (bool)contractProperty.PropertyType.InvokeMember("IsValid", BindingFlags.InvokeMethod, null, null, null);
И
var childInstance = (ISampleContract)contractProperty;
Проблема с первым заключается в том, что я не могу передать значение null в качестве цели для InvokeMember, поскольку IsValid () не является статическим (и не может быть, поскольку я сосредоточен на фактическом экземпляре). Второй - просто неудачный актерский состав, но это суть того, чего я хочу достичь.
Пример кода выше - просто минималистский пример того, чего я хочу достичь. Полный код является частью самопроверяющегося DTO, который рекурсивно проверяет всю иерархию и возвращает то, что у детей есть проблемы с проверкой и чем они являются.
Любая помощь будет принята с благодарностью.