Невозможно получить доступ к переменной экземпляра с помощью метода расширения с помощью лямбды

Я создал метод расширения в соответствии с ответом на SO здесь

public class AcObject
{
    public int Id { get; set; }
}

public static Dictionary<string, string> GetValidationList<AcObject, TProperty>(
    this AcObject source,
    Expression<Func<AcObject, TProperty>> propertyLambda)
{
    // Autocomplete here only shows static members for 'source'
    // I am expecting to be able to do source.Id
}

введите описание изображения здесь

Любой, кто может объяснить мне, почему я не могу использовать source.Id в приведенном выше сценарии и предложите, где я могу найти подобное решение?

Если я установлю точку останова внутри GetValidationList() метод я могу навести курсор мыши на источник и увидеть экземпляр и его свойства, как и следовало ожидать... я просто не могу использовать его в VS.

введите описание изображения здесь

Моя общая цель - сделать следующее

public class AcObject
{
    public int Id { get; set; }
    public string Type { get; set; }
}

public class OtherObject : AcObject
{
    public string AssetTag { get; set; }
}

// somewhere else in code
AcObject myObject = new AcObject();
myObject.GetValidationList(a => a.Type);

// Along with using the type that inherits it
OtherObject myOtherObject = new OtherObject();
myOtherObject.GetValidationList(a => a.Type);

// In some kind of extension method lambda magic
{
    Console.WriteLine(source.Id);
}

Редактировать - Обновлено, чтобы включить требование, чтобы оно работало с базовыми классами, а также с теми, которые его наследуют.

2 ответа

Решение

Измените подпись вашего метода расширения следующим образом: (удалите начальный "AcObject")

public static Dictionary<string, string> GetValidationList<TProperty>(
    this AcObject source, Expression<Func<AcObject, TProperty>> propertyLambda)

В вашем последнем фрагменте кода есть опечатка:

AcObject myObject = new AcObject();
myObject.GetValidationList(a => a.Type);  // call the extension method on the instance

Те параметры типа, которые вы включили (AcObject и TProperty), являются заполнителями, представляющими фактические типы, которые вы указываете при вызове метода. Называя первый "AcObject" в вашем методе, вы скрываете фактический класс, также называемый "AcObject" (поэтому "AcObject" в this AcObject source больше не ссылается на ваш класс).


Обновив свой вопрос, измените свою подпись следующим образом. Вначале вы правильно сделали, просто измените имя параметра типа с "AcObject" на другое, отличное от имени вашего класса, например "T":

public static Dictionary<string, string> GetValidationList<T, TProperty>(
    this T source, Expression<Func<T, TProperty>> propertyLambda)

Тогда вы можете назвать это с вашими различными классами:

AcObject myObject = new AcObject();
myObject.GetValidationList(a => a.Id);

OtherObject myOtherObject = new OtherObject();
myOtherObject.GetValidationList(a => a.AssetTag);
public static class stat
    {
        public static void GetValidationList(  this AcObject source )
        {
            Console.WriteLine(source.Id);

        }
    }


    public class AcObject
{
    public int Id { get; set; }
}

Использование:

    AcObject myObject = new AcObject();
    myObject.GetValidationList();
Другие вопросы по тегам