Есть ли способ вывести тип действия или полное действие? - PullRequest
1 голос
/ 05 декабря 2010

Я часто (слишком) использую конструкцию, подобную следующей:

class MyClass
{
    public TypeA ObjectA;
    public TypeB ObjectB;
    public TypeC ObjectC;
    public List<TypeD> ListOfObjectD = new List<TypeD>();

    public void DoSmth()
    {
        return SomeConstruct(
            /*...*/
            new Setter<TypeA>(a => ObjectA = a), // these are the
            new Setter<TypeB>(b => ObjectB = b), // things I'm trying
            new Setter<TypeC>(c => ObjectC = c), // to make shorter
            new Setter<TypeD>(d => ListOfObjectD.Add(d)),
            /*...*/
        );
    }
}
class Setter<T>
{
    public Action<T> Action;

    public Setter(Action<T> action)
    {
        Action = action;
    }
}

Есть ли какой-нибудь способ для класса Setter выводить тип действия и создавать стандартное (T obj) => Member = obj действие потолько передать член каким-либо образом?Я думаю о чем-то вроде:

new Setter(ObjectA)

, что, конечно, не является допустимым синтаксисом, но должно дать вам представление о том, чего я пытаюсь достичь.Я использую эту конструкцию буквально сотен времени в моем коде, поэтому код, сохраненный этим небольшим изменением, будет огромным.


Редактировать: Добавленопример TypeD.Часть

new Setter<TypeD>(d => ListOfObjectD.Add(d))

может быть упрощена до

new Setter<TypeD>(ListOfObjectD.Add)

, что удивительно, поскольку она вырезана из избыточного кода.Если бы можно было только сделать вывод <TypeD>, это было бы идеально.Я ищу что-то подобное для остальных.

@ Lazarus - в основном цель состоит в том, чтобы вернуть сеттеры, чтобы другие объекты могли устанавливать определенных членов класса (или это может делатьдругие вещи, определенные в действии) без доступа к самому классу, только объект Setter.Полный список причин длинный и запутанный, но структурирование программы работает как шарм, и я сомневаюсь, что нужно изменить (пример, конечно, упрощен и не имеет смысла как есть).


Редактировать 2: Я нашел хороший способ упростить вещи для List:

static class SetterHelper
{
    public static Setter<T> GetSetter<T>(this List<T> list)
    {
        return new Setter<T>(list.Add);
    }
}

Теперь я могу просто использовать это:

ListOfObjectD.GetSetter()

, который отлично работает!почему я не могу сделать то же самое для T напрямую?Я попробовал это:

static class SetterHelper
{
    public static Setter<T> GetSetter<T>(this T item)
    {
        return new Setter<T>(t => item = t); // THIS DOESN'T SET THE PASSED MEMBER
    }
}

Конечно, это не будет работать так, как задумано, потому что он будет устанавливать элемент, но не пропущенный член.Я попытался добавить ref как (ref this T item), но он не скомпилируется: (... Это было бы идеально.

1 Ответ

2 голосов
/ 05 декабря 2010

Лучшее, что я могу вам предложить, это следующий синтаксис:

Setter.For( () => ObjectA );

с использованием этого вспомогательного класса

static class Setter
{
    public static Setter<T> For<T>(Expression<Func<T>> e)
    {
        ParameterExpression[] args = { Expression.Parameter(((e.Body as MemberExpression).Member as FieldInfo).FieldType) };
        Action<T> s = Expression.Lambda<Action<T>>(Expression.Assign(e.Body, args[0]), args).Compile();

        return new Setter<T>(s);
    }
}
...