Сначала я определил класс, например:
class UserInfo
{
public string UserName { get; set; }
public int Age { get; set; }
public bool State { get; set; }
public void eat()
{
}
}
Затем в классе Program
определили метод Update2
:
private void Update2<T>(Action<T> exp)
{
}
Метод Update2
можно вызвать так:
Update2<UserInfo>(u => {
u.Age = 120;
u.State = false;
u.UserName = "what's name";
});
Можно ли узнать обновленные свойства и значение? Или могу ли я использовать выражение, чтобы узнать это?
обновлять
private void Update1<T>(Expression<Action<T>> exp)
{
}
если вы используете метод Update1
, вы можете называть его только лайками Update1<UserInfo>(u => u.eat());
. Если вы используете
Update1<UserInfo>(u => {
u.Age = 123;
u.State = false
});
возникнет ошибка: Ошибка (активная) CS0834. Лямбда-выражение с телом инструкции невозможно преобразовать в дерево выражений.
Можете ли вы объяснить немного больше, что вы собираетесь Update2
делать?
В чем/где именно здесь вопрос? Ваш анонимный объект, переданный в Update2, существует только во время его вызова, до или после него проверять нечего. Ваши намерения мне не ясны.
кто сказал, что вы вообще обновляете какую-либо собственность? Вы также можете сделать Update2<UserInfo>(u => Console.WriteLine("Hello"))
. Единственный способ — проанализировать выражение, в котором используется Expression<Action<T>>
вместо Action<T>
.
с точки зрения MakePeaceGreatAgain, этот недавний вопрос может представлять интерес
@Sweeper, на самом деле я хочу использовать дерево выражений. и я также определил метод Private void Update1<T>(Expression<Action<T>> exp) { ... }```.
@Магнус, на самом деле я пытаюсь написать функцию обновления sql. я хочу использовать u => { u.Age = 123; ... }
Посмотрите здесь Можно ли использовать выражение LINQ с подписью делегата для получения параметров?
@MakePeaceGreatAgain, @rotabor мне нужно выражение u => { u.age = ... }
, а не еще один вызов метода
Это была не моя точка зрения. Дело в том, что внутри вашего Update2
-метода вы просто понятия не имеете, какой тип Action
был предоставлен, это может быть буквально всё, а не только задание. Опять же: используйте Expression
, если хотите получить представление о делегате.
@MakePeaceGreatAgain, да, ты прав.
Разве вы не видели ошибку: дерево выражений не может содержать оператор присваивания?
@shingo, если использовать только Update2
, ошибки не будет.
@goldii ты не можешь использовать для этого EF?
@Магнус, спасибо за предложение. но я хочу написать свой собственный.
Итак, вы пытаетесь написать свой собственный поставщик linq to SQL?
Предполагаете ли вы, что в аргументе u
есть только присвоения свойствам Update2
? Может ли вызывающий абонент, например, установить какое-то свойство, а затем вызвать другой метод?
@Sweeper, задавай только значение свойства. никакой другой вызов метода
@Магнус. Да, это
Дерево выражений может не содержать оператора присваивания, но вы можете использовать Expression<Func<T>>
вместо Action<T>
, чтобы прочитать MemberInitExpression
:
private void Update1<T>(Expression<Func<T>> exp)
{
if (exp.Body is MemberInitExpression exp2)
{
foreach (var b in exp2.Bindings)
{
if (b is MemberAssignment ma)
{
// left property
Console.WriteLine(ma.Member);
// right expression
Console.WriteLine(ma.Expression);
}
}
}
}
Update1(() => new UserInfo
{
Age = 120,
State = false,
UserName = "what's name",
});
Поскольку это чтение выражения, оно фактически не выделяет этот объект.
Это умный метод. Если нет лучшего способа, возможно, это единственный способ
Вы пытаетесь избежать использования дерева выражений? ИМХО, это наиболее естественный подход.