有没有办法推断出Action类型或完整的Action?

时间:2010-12-05 19:04:54

标签: c# types action type-inference

我发现自己(也经常)使用如下构造:

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类是否有任何方法可以通过仅以某种方式传递Member来推断Action的类型并创建标准(T obj) => Member = obj Action?我想的是:

new Setter(ObjectA)

当然这不是有效的语法,但应该让你知道我想要实现的目标。我在我的代码中使用这个构造字面数百,所以代码 通过这个小小的变化得到了巨大的帮助。


修改:添加了TypeD示例。部分

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

可以简化为

new Setter<TypeD>(ListOfObjectD.Add)

这很棒,因为它会从冗余代码中删除。如果只能推断<TypeD>,那将是完美的。我正在为其他人寻找类似的东西。

@Lazarus - 基本上目的是返回setter,因此其他对象可以设置类的某些成员(或者它可以执行Action中定义的其他内容)而无需访问类本身,仅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 个答案:

答案 0 :(得分:2)

我能为您提供的最佳语法如下:

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