[ACCEPTED]-Is there any way to pass the setter of a property to a delegate?-properties
The answer to your question is going to 37 be no. At least as far as C# is concerned.
Why? Let's 36 say that you have the following object:
public class Foo
{
public int SomeProp { get; set; }
}
you 35 know that under the hood the compiler will 34 autogenerate int get_SomeProp() and void 33 set_SomeProp(int value) for you (plus the 32 backing field), so you should be able to 31 do this:
var someMethod = foo.get_SomeProp;
and you can - almost. You get this 30 error from the compiler: "cannot explicitly 29 call operator or accessor". So without 28 reflection or a wrapper, you're SOL. Maybe. I 27 say maybe because just because C# doesn't 26 let you treat a getter or setter like a 25 real method, it doesn't mean that some other 24 .NET language can't. For example, I can 23 write this in F#:
namespace PassSetter
module mucker =
let muckWithFoo (aFoo:Foo) =
aFoo.set_SomeProp
and now muckWithFoo is 22 a function declared as Foo->(int->unit), which 21 is equivalent to a method that returns delegate 20 void d(int value). In essence, you can 19 use another module to break the C# compiler 18 constraint, if need be. I picked F# only 17 because I have the compiler handy, but I 16 bet you could do this with C++/CLI as well.
The 15 main difference between this and a wrapper 14 is that even though you still need to write 13 a wrapper for every type for which you would 12 like to get a delegate from, that wrapper 11 doesn't end up attached to the final delegate.
I 10 don't know what your issue is with the "no 9 reflection" constraint - is it that you're 8 running in an environment that forbids reflection 7 or that you believe that you're so performance 6 bound that you can't afford to use reflection. If 5 it's the latter, then there are several 4 more options open to you that give you much 3 better performance than simply reflection 2 to get the property set method and then 1 invoke it (effectively call by name).
Define this helper function(You'll need 5 to add the error checking):
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;
}
And use it like 4 this:
Action<MyClass,int> setter=GetSetter((MyClass o)=>o.IntProperty);
This is not exactly what you want(It 3 uses reflection), but probably as close 2 as you'll get. The returned delegate is 1 the setter itself, no wrapper.
Why not use an interface?
interface IPropertySetter {
string Property { set; }
}
Have your class 1 implement it:
class MyClass : IPropertySetter {
public string Property { get; set; }
}
And pass it to your object:
var c = new MyClass();
myObject.MyMethod(c);
...
void MyMethod(IPropertySetter setter) {
setter.Property = someValue;
// you can also store the "setter" and use it later...
}
C# does not allow this (because of the specialname 5 attribute the compiler generates on the 4 set_AnotherProperty method), however J# would 3 because it does not support the property 2 syntax.
This is what the code would look like.
Action<int> x = set_AnotherProperty(1);
However, the 1 C# compiler tells you
Error 3 'Program.AnotherProperty.set':
cannot explicitly call operator or accessor
I am pretty sure the answer is no. The most 4 common approach to this is to use lambda 3 expressions, see for example the common 2 solution to hard-coded INotifyPropertyChanged 1 strings:
There are no other magic ways!
If you don't want to pass a wrapper around 4 a property's setter, you can go the other 3 way around and let the setter be a wrapper 2 around a method. For example:
public MyClass
{
private Foo _myProperty;
public Foo MyProperty
{
get { return _myProperty; }
set { MyPropertySetter(value); }
}
public void MyPropertySetter(Foo foo)
{
_myProperty = foo;
}
}
then do:
myObject.Mymethod(myOtherObject.MyPropertySetter);
It's 1 not pretty, but it does what you want done.
For your constraints, it seems you can't 9 use properties at all. If the performance 8 considerations are so strong that you can't 7 simply wrap the setter in a lambda, then 6 you might want to change your style of development. That's 5 normally what's done in extreme cases of 4 code tuning. Put on your Java hat and create 3 explicit setter and getter methods in your C# code:
class MyClass {
private string _value;
public void setProperty(string value) { _value = value; }
}
No properties 2 involved... But, how much that really buys you 1 over lambdas? I wouldn't think it's noticeable.
A property can be wrapped in a delegate, if 6 intellectual purity and lexical beauty are 5 not synonymous. Of course it is not quite 4 a property, with null being a trigger for 3 read/write operations and the need for the 2 'called' to treat it like a function, after 1 all.
xType1 xProperty1 {get;set;}
xType2 xProperty1 {get;set;}
xCallingFunction()
{
....
xCalledFunction(
((s)=> s == null ? xProperty1 : (xProperty1 = s)),
((s)=> s == null ? xProperty2 : (xProperty2 = s))
);
....
}
....
xCalledFunction( Func<xType, xType> parm1, Func<xType2, xType2> parm2 )
var p1 = parm1(null);
parm2( newValue );
parm1( parm1(null) + 16 );
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.