Red Taz
Red Taz

Reputation: 4179

C# Property Reference

Given the following code;

public class CustomControl {
    private object _dataItem;

    public object DataItem {
        get { return _dataItem; }
        set { _dataItem = value; }
    }

    public void Update(ref string t) {
        t = "test";
    }
}

public class Consume {
    public void Example() {
        CustomControl ctrl = new CustomControl();
        ctrl.DataItem = anyObject.anyProperty;

        string prop = anyObject.anyProperty;
        ctrl.Update(ref prop);
        anyObject.anyProperty = prop;
    }
}

How can I change it so that the DataItem property is itself a reference, allowing you to pre-emptively set it to point to a variable thus allowing you to call Update() without any parameters.

So the Consume class would then look similar to;

public class Consume {
    public void Example() {
        CustomControl ctrl = new CustomControl();
        ctrl.DataItem = anyObject.anyProperty;
        ctrl.Update();

        // anyObject.anyProperty has been updated to "test"
    }
}

So the assigment of anyObject.anyProperty is then handled internally within CustomControl

Upvotes: 3

Views: 1884

Answers (2)

AakashM
AakashM

Reputation: 63378

You need to store the act of setting something to a string, so store an Action<string>:

public class CustomControl {
    public Action<string> SetData { get; set; }

    public void Update() {
        // TODO nullity check
        SetData("test");
    }
}

Then Consume would look like:

public class Consume {
    public void Example() {
        CustomControl ctrl = new CustomControl();

        // store {the act of setting this property of this object to a string}
        ctrl.SetData = s => anyObject.anyProperty = s;

        ctrl.Update();
    }
}

The Update call will set anyObject.anyProperty to test. Note that you are storing specifically the act of setting this property of the particular anyObject you refer to in the assignment to SetData.


To expand on the lambda: we want to create a value of type Action<string>, that is, a thing which takes a string and returns no result. Such a thing is going to be executable code. Prior to C# 3, to create a 'value' that was executable code, we would have had to do something like:

    ctrl.SetData = delegate(string s) { someObject.SomeProperty = s; };

With this syntax it's more obvious that we're creating a method - it has a { } delimited body, it has statements in it, and it's clear there is a string parameter that is used by the body.

One thing achieved by lambda expressions in C# 3 is the ability to condense this down; loosely, the whole of

// not compilable code
delegate(parameters) { body; }

can be replaced with

// not compilable code
(parameters) => body;

and in the case where there's only one parameter

// not compilable code
parameter => body;

which is what we have here: the expression assigned to ctrl.SetData is a piece of behaviour that accepts a string (s) and sets anyObject.anyProperty to that string. The real power is in the way the C# compiler can work out the types to it know we're creating an Action<string>.

Upvotes: 5

tvanfosson
tvanfosson

Reputation: 532665

At first I didn't understand what you're trying to do. What you're looking for is the Adapter or Facade pattern. That is, you have an object with a particular interface, but you need to adapt it to a different interface or provide a simpler interface.

One way to implement these patterns is to use composition and delegate the new interface to methods on the existing interface.

 public interface IUpdatable<U>
 {
      void Update( U newValue );
 }

 public abstract class CustomControl<T,U> : IUpdatable<U>
     where T : Control
 {
     private T  Control { get; set; }

     protected CustomControl( T control )
     {
          this.Control = control;
     }

     public abstract void Update( U newValue );
 }

 public class TextBoxFacade : CustomControl<TextBox,string>, IUpdatable<string>
 {
     public TextBoxFacade( TextBox textbox ) : base(textbox) { }

     public override void Update( string newValue )
     {
         this.Control.Value = newValue;
     }
 }

Upvotes: 1

Related Questions