[C# 3.0] Делегаты для свойства
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var myClass = new MyClass;
myClass.Property(x => x.MyProperty).Value = "Test!";
Console.WriteLine(myClass.MyProperty);
}
}
public class MyClass
{
private string myProperty;
public string MyProperty
{
get
{
return myProperty;
}
set
{
myProperty = value;
}
}
}
public static class Util
{
public static IPropertyDelegate<TValue> Property<TEntity, TValue>(
this TEntity entity, Expression<Func<TEntity, TValue>> expression)
{
return new PropertyDelegate<TEntity, TValue>(entity, expression);
}
private class PropertyDelegate<TEntity, TValue> : IPropertyDelegate<TValue>
{
private readonly TEntity entity;
private readonly Expression<Func<TEntity, TValue>> expression;
public PropertyDelegate(TEntity entity, Expression<Func<TEntity, TValue>> expression)
{
this.entity = entity;
this.expression = expression;
}
public TValue Value
{
get
{
//TODO: optimize
return expression.Compileentity);
}
set
{
//TODO: optimize
PropertyInfoMemberExpression)expression.Body).Member).SetValue(entity, value, null);
}
}
}
}
public interface IPropertyDelegate<TValue>
{
TValue Value { get; set; }
}
}
Некоторые ошибки будут обнаружены только в рантайме:
1. отсутствие сеттора у свойства
2. лямбда выражение отличное от простого вызова свойства
Но это мелочи, с которыми можно жить
порусски напиши - чего хотел - чего добился?
порусски напиши - чего хотел - чего добился?Ситуация общая, но поясню на конкретном примере. В аспнете двунаправленный датабайндинг осуществляется через метод Bind("FieldName"). В чем фишка такой записи — в том что стрингом ты сразу определяешь и геттор и сеттор, т.е. фраймворк будет дергать либо геттор, либо сеттор в зависимости от направления байндинга. Но стринг это не типизировано и поэтому плохо. Теперь вместо стринга ты можешь передавать Expression (выглядит как лямбда выражение x => x.MyProperty).
Плохо что в MemberExpression нет доступа до владельца свойства.
Плохо что в MemberExpression нет доступа до владельца свойства.что такое владелец свойства?
до типа Type можно добраться
до аргумента лямбды тоже
Конкретного экземпляра объекта конечно нет, и не должно быть.
Конкретного экземпляра объекта конечно нет, и не должно быть.Если используется замыкание то почему бы и нет.
Мне как то не очевидно почему бы не дать в первом случае добраться до конкретного значения.
var a = 1;
Expression<Func<int, int>> ex1 = x => x + a;
Expression<Func<int, int>> ex2 = x => x + 1;
Или я плохо искал?
Мне как то не очевидно почему бы не дать в первом случае добраться до конкретного значения.значение "a" берется на момент вызова делегата, т.е. ты можешь менять его и каждый раз будет использоваться текущее значение. Какое конкретное значение ты имеешь ввиду?
Какое конкретное значение ты имеешь ввиду?Текущее, как же еще.
Текущее, как же еще.должна быть такая возможность, сейчас студии нет, завтра посмотрю
с чего ты взял, что кто-то ВООБЩЕ заинтересуется?
ну вот я заинтересовался. а вот какова цель твоего поста?
Тред апнуть.
Меня давно этот вопрос занимает: стаднартное прописывание в биндинге свойств в виде обычных стрингов - ужас тестинга\суппорта, а другие варианты заставляют фактически дублировать код в геттерах-сеттерах.
Твое решение - тоже в некотором смысле полумера, но лучше, чем было.
Оставить комментарий
6yrop
в продолжение вот этого треда (тред уже ушел в архив)Вероятно, в C# 3.0 уже можно писать как я хотел. Можно добиться того, чтобы функция из последнего поста предыдущего треда выглядела вот так
Т.е. передаем только геттер, а сеттор будем вызывать используя Expression и совсем немного рефлекшена
P.S. завтра попробую реализовать это