Хорошо, во-первых, здесь не происходит ничего динамического, но, как вы говорите, проблема здесь:
parentProperty(e) = 0;
parentProperty
- это функция, вот и все. Это не действительно собственность. Это позволяет вам получить от T
до long
- и все. Это может быть что угодно - представьте Func<string, long>
, который вернул x.Length * 5
. Что будет означать «установить» это (скажем) 3?
Если вы хотите иметь возможность установить значение, вам потребуется действие, например,
public static List<T> Fix<T>(this List<T> enumeration,
Func<T, long> idProperty,
Func<T, long> parentGetter,
Action<T, long> parentSetter)
{
enumeration = enumeration.Select(e =>
{
long parentId = parentGetter(e);
if (!enumeration.Any(x => idProperty(x) == parentId))
{
parentSetter(e, 0);
}
return e;
}).ToList();
return enumeration;
}
и назовите это так:
Test.Fix(a, x => x.ID, x => x.Parent, (x, v) => x.Parent = v).Dump();
Обратите внимание, что я немного изменил логику в Any
, потому что ваша текущая логика не имела смысла - она не использовала e
в тесте.
Однако это не очень хорошее применение LINQ - LINQ разработан без побочных эффектов. Учитывая, что вы возвращаете только те же элементы, что и раньше, вы можете ничего не возвращать, а просто использовать цикл foreach
:
public static void Fix<T>(this List<T> enumeration,
Func<T, long> idProperty,
Func<T, long> parentGetter,
Action<T, long> parentSetter)
{
foreach (T item in enumeration)
{
long parentId = parentGetter(e);
if (!enumeration.Any(x => idProperty(x) == parentId))
{
parentSetter(e, 0);
}
}
}
Я бы лично затем изменил бы это на:
public static void Fix<T>(this List<T> enumeration,
Func<T, long> idProperty,
Func<T, long> parentGetter,
Action<T, long> parentSetter)
{
HashSet<long> validIds = new HashSet<long>(enumeration.Select(idProperty));
foreach (T item in enumeration.Where(x => !validIds.Contains(parentGetter(x)))
{
parentSetter(e, 0);
}
}