Как использовать интерфейс и рефлексию для вызова нужного сеттера без передачи типа напрямую?
Что проверяют
Понимаете ли вы, когда рефлексия действительно нужна, а когда задача решается интерфейсом и обобщениями без неё. Следом обычно спрашивают про цену рефлексии и способы её снизить: кеш PropertyInfo, скомпилированные делегаты, генераторы исходного кода.
Как отвечать
Начните с того, что тип передавать не нужно: он есть у самого объекта, obj.GetType(). Дальше каркас:
- поиск свойства:
type.GetProperty(name, BindingFlags.Public | BindingFlags.Instance), затем проверкаCanWrite, и только потомSetValue(obj, value); - приведение значения:
PropertyInfo.SetValueстроку в число сам не превратит и броситArgumentException. Приводите черезConvert.ChangeType, не забывая проNullable.GetUnderlyingType, или черезTypeConverter; - роль интерфейса: объявите контракт вроде
ISettable<T> { void Set(T value); }и найдите реализацию черезtype.GetInterfaces(), взяв аргумент обобщения изGetGenericArguments(). Рефлексия нужна один раз, чтобы выбрать реализацию, а сам вызов остаётся типобезопасным; - без рефлексии вовсе: обобщённый метод
Set<T>(ISettable<T> target, T value)выводит тип из аргумента, и нужную реализацию выбирает компилятор. Когда значение приходит какobject, выбрать перегрузку во время выполнения поможетdynamic; - производительность:
PropertyInfoкешируйте по типу вConcurrentDictionary, а для горячего пути соберите делегат черезExpression.Lambda<Action<object, object>>(...).Compile()илиMethodInfo.CreateDelegate, если типы известны. Вызов готового делегата по скорости близок к прямому.
Хорошо упомянуть trimming и Native AOT: поиск свойства по строковому имени ломается, если триммер вырезал метаданные. Там нужны атрибуты [DynamicallyAccessedMembers] или генератор исходного кода.
Где спотыкаются
Сразу пишут рефлексию, хотя интервьюер ждал, что вы заметите решение через интерфейс и обобщения.
Передают значение не того типа и удивляются исключению во время выполнения. Без явного приведения SetValue работает только с совместимым типом.
Вызывают GetProperty на каждый объект в цикле. На миллионах записей это заметно, а кеш по типу решает проблему парой строк.