pyo*_*yon 12 c# delegates properties
我知道这个问题已被提出,但这次我有两个额外的限制:
不能使用反射.
我不想在属性的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做到这一点.
这和包装之间的主要区别是,即使你仍然需要编写的每一个类型的包装,而您想获得从一个委托,该封套并没有结束附着在最终委托.
我不知道你的问题是什么与"无反射"约束 - 你是在一个禁止反射的环境中运行,还是你认为你的性能受限,你不能使用反射.如果它是后者,那么还有几个选项对你开放,它们比简单的反射提供了更好的性能,以获取属性集方法然后调用它(有效地通过名称调用).
定义这个辅助函数(你需要添加错误检查):
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本身,没有包装器.
我很确定答案是否定的。最常见的方法是使用 lambda 表达式,例如,请参阅硬编码 INotifyPropertyChanged 字符串的常见解决方案:
没有其他神奇的方法了!
归档时间: |
|
查看次数: |
8529 次 |
最近记录: |