有没有办法将属性的setter传递给委托?

pyo*_*yon 12 c# delegates properties

我知道这个问题已被提出,但这次我有两个额外的限制:

  1. 不能使用反射.

  2. 我不想在属性的setter周围传递一个包装器.我想通过setter本身:

    // NO! NO! NO!
    myObject.MyMethod(value => anotherObject.AnotherProperty = value);
    
    Run Code Online (Sandbox Code Playgroud)

pli*_*nth 11

你的问题的答案是否定的.至少就C#而言.

为什么?假设您有以下对象:

public class Foo
{
    public int SomeProp { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

你知道,在引擎盖下,编译器会自动生成INT get_SomeProp()和空set_SomeProp(int值)为您(加上支持字段),所以你应该能够做到这一点:

var someMethod = foo.get_SomeProp;
Run Code Online (Sandbox Code Playgroud)

你可以 - 几乎.您从编译器中收到此错误:"无法显式调用运算符或访问器".所以没有反射或包装,你就是SOL.也许.我说也许是因为C#不会让你像对待真正的方法一样对待getter或setter,这并不意味着其他一些.NET语言不能.例如,我可以在F#中写这个:

namespace PassSetter

module mucker =
    let muckWithFoo (aFoo:Foo) =
        aFoo.set_SomeProp
Run Code Online (Sandbox Code Playgroud)

现在muckWithFoo是一个声明为Foo - >(int-> unit)的函数,它相当于一个返回委托void d(int value)的方法.实质上,如果需要,您可以使用另一个模块来破坏C#编译器约束.我选择F#只是因为我有编译器方便,但我敢打赌你也可以用C++/CLI做到这一点.

这和包装之间的主要区别是,即使你仍然需要编写的每一个类型的包装,而您想获得从一个委托,该封套并没有结束附着在最终委托.

我不知道你的问题是什么与"无反射"约束 - 你是在一个禁止反射的环境中运行,还是你认为你的性能受限,你不能使用反射.如果它是后者,那么还有几个选项对你开放,它们比简单的反射提供了更好的性能,以获取属性集方法然后调用它(有效地通过名称调用).

  • 概念纯度是一个值得称赞的目标,但在某些时候,你必须在它和实用性之间取得平衡.Lambda包装器在可读性方面是完全可以接受的,并且可能性能良好.如果它不够高效,那么有更多的选择,但它们只会变得更加丑陋. (3认同)
  • @plith将属性名称放在字符串文字中通常是个坏主意.我更喜欢Lamda技巧. (3认同)

Cod*_*aos 6

定义这个辅助函数(你需要添加错误检查):

Action<TObject,TValue> GetSetter<TObject,TValue>(Expression<Func<TObject,TValue>> property)
{
    var memberExp=(MemberExpression)property.Body;
    var propInfo=(PropertyInfo)memberExp.Member;
    MethodInfo setter=propInfo.GetSetMethod();
    Delegate del=Delegate.CreateDelegate(typeof(Action<TObject,TValue>),setter);
    return (Action<TObject,TValue>)del;
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

Action<MyClass,int> setter=GetSetter((MyClass o)=>o.IntProperty);
Run Code Online (Sandbox Code Playgroud)

这不是你想要的(它使用反射),但可能尽可能接近你.返回的委托是setter本身,没有包装器.


Col*_*inE 1

我很确定答案是否定的。最常见的方法是使用 lambda 表达式,例如,请参阅硬编码 INotifyPropertyChanged 字符串的常见解决方案:

http://10rem.net/blog/2010/12/16/strategies-for-improving-inotifypropertychanged-in-wpf-and-silverlight

没有其他神奇的方法了!