开发者

Is there any way to infer an Action type, or a full Action?

开发者 https://www.devze.com 2023-01-28 19:09 出处:网络
I find myself (too) often using a construct like the following: class MyClass { public TypeA ObjectA; public TypeB ObjectB;

I find myself (too) often using a construct like the following:

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 =>开发者_Go百科; ListOfObjectD.Add(d)),
            /*...*/
        );
    }
}
class Setter<T>
{
    public Action<T> Action;

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

Is there any way for the Setter class to infer the type of the Action and create the standard (T obj) => Member = obj Action by only passing the Member in some way? I'm thinking of something like:

new Setter(ObjectA)

which of course is not valid syntax, but should give you an idea what I'm trying to achieve. I'm using this construct literally hundreds of time in my code, so the code saved by this small change would be tremendous.


Edit: Added the TypeD example. The part

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

can be simplified to

new Setter<TypeD>(ListOfObjectD.Add)

which is awesome because it cuts from the redundant code. If only <TypeD> could also be inferred it would be perfect. I'm looking for something like this for the others.

@Lazarus - basically the purpose is to return setters, so other objects can set certain members of the class (or it can do other stuff defined in the Action) without accessing the class itself, only the Setter object. The full list of reasons is long and convoluted, but the structuring of the program works like a charm and I doubt needs changing (the example of course is simplified and doesn't really make sense as is).


Edit 2: I found a good way to simplify things for List's:

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

Now I can just use this:

ListOfObjectD.GetSetter()

which works perfectly! why can't I do the same for T directly? I tried this:

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
    }
}

Of course it won't work as intended because it will set item, but not the passed member. I tried adding ref as (ref this T item) but it won't compile :(... It would have been perfect.


Best I can offer you is the following syntax:

Setter.For( () => ObjectA );

using this helper class

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);
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消