I have two simple questions, based on the fact that I am extending an existing class...
1) I am implementing some custom properties, and I would like that whenever their values change a specific (parameterless) function be called. Of course, if there was no need to call the function I could use the traditional { get; set; } syntax with no need for an additional variable. However, and even if the only thing I modify in the set accessor is the call to the other function, I must declare a private variable so that I can specify the get and set accessors myself... Isn't there a simpler way to do this without declaring so many variables? Isn't there something like a gerenal "property change" event?
2) Since I am overriding a .NET user control, I would like to change the category under which some of the base properties appear. At the moment, and just to use the [Category("")] syntax, I must declare those properties as new and implement get and set referring to the base classe's properties. Isn't there a simple way to do this?
Maybe you should look into the INotifyPropertyChanged interface. Below is some example code that uses it. I use this interface to accomplish data binding in WPF. You could handle the event, discover the property that changed and act accordingly. You could even raise the event on another thread (PropertyChanged.BeginInvoke()) if you wanted the setter to be asynchronous...
using System;
using System.ComponentModel;
public class Foo : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
RaisePropertyChanged("Name");
}
}
}
C# doesn't support this natively, but you can go AOP via Interceptors in Windsor, which will give you a hit in runtime or use something like PostSharp to generate code for the calls to the events. PostSharp will inject the IL code after the assemblies are created, so it shouldn't give as big as performance hit as Windsor during runtime.
It is a good idea to read a bit more about AOP as well.
If you are trying to capture events off of properties accessed without a lot of duplicated coding while maintaining a seperation of concerns then you could look into Aspect Oriented Programming techniques using frameworks such as Castle, but beware that this is a complicated topic that includes hard choices about the architecture of your application.
1) No there isn't a property change event. If you're insistent on not creating extra variables you could go the AOP route. You should be satisfied without AOP unless there are countless properties you're dealing with, in which case you could opt for code-generation (maybe write a python/ruby script to generate code or use a common code generator)
2) I don't think you can change properties pre-runtime (in Visual Studio) without code generation.
Maybe I'm off here but what about something like this for #1:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace EraseMe2
{
class Program
{
static void Main(string[] args)
{
Test t = new Test();
t.MyProperty = 100;
t.MyProperty = 500;
}
}
class Test
{
public int set(ref int prop, int val)
{
prop = val;
Console.WriteLine(String.Format("{0} changed to {1}", prop.GetType().Name, val.ToString()));
return val;
}
private int _myProperty;
public int MyProperty
{
get { return _myProperty; }
set
{
_myProperty = set(ref _myProperty, value);
}
}
}
}
Related
I am working on a project with over 30 properties that are constantly being updated using data binding. The way i'm fetching the new values sent by the server is with event aggregator, which updates the properties. So far, here's how I got it working
Event Class
public class Zone1TempEvent : PubSubEvent<int>
{
}
Property
private int _zone1Temp;
public int Zone1Temp
{
get { return _zone1Temp; }
set { SetProperty(ref _zone1Temp, value); }
}
Subscribe
eventAggregator.GetEvent<Zone1TempEvent>().Subscribe(tempZone1Update);
Method
private void tempZone1Update(int value) { Zone1Temp = value; }
Publish
private void checkResponsability(ItemValueCallback itemValue)
{
switch ((string)itemValue.ClientHandle)
{
case "Zone1_Temp":
int Zone1Temp = Int32.Parse((string)itemValue.Value);
_eventAggregator.GetEvent<Zone1TempEvent>().Publish(Zone1Temp);
break;
}
}
However, I can't imagine doing this 30 times. I am looking for an alternative. I would like to avoid having to create a class for each event, as well as a method for each property. Is it possible to have one generic class called UpdatePropertyEvent, and use this to do so.
Or maybe do something inspired by this thread with enums?
Mixing enums with event classes in an event aggregator
Thanks
Instead of using the EventAggregator, your service can implement IPropertyChanged (and the models returned from the service can, depending on your scenario ). This way you have to react to just one event.
Also, you could just publish a single event that carries the two string values, like class ServerUpdatedEvent : PubSubEvent<PropertyValuePair> and do the parsing and distributing
to properties in the view model.
Example:
// ...service...
private void checkResponsability(ItemValueCallback itemValue)
{
_eventAggregator.GetEvent<ServerUpdatedEvent>().Publish(new PropertyValuePair((string)itemValue.ClientHandle,(string)itemValue.Value);
}
// ...view model or intermediate service...
private void OnServerUpdate(PropertyValuePair data)
{
switch (data.Property)
{
case "Zone1_Temp": Zone1Temp = int.Parse(data.Value); break;
}
}
If your properties can be named like the events or you put attributes on them, you can use reflection to find the property for an incoming event. Reflection is slow, though, so that if you have lots of events, you might need some type of caching.
Something like this could work for you, too.
C# allows the creation of a property as below:
public string SomeRandomText
{
get; set;
}
The framework handles the creation of the backing variable for this property. How can I have such a property and still have change notification?
Is this allowed in a class that implements INotifyPropertyChanged?
public string SomeRandomTextBeingNotified
{
get;
set
{
NotifyPropertyChanged("SomeRandomTextBeingNotified");
}
}
You can't use automatic properties when trying to use this. You'll need to creating a backing store:
private string _someRandomText;
public string SomeRandomText {
get { return _someRandomText; }
set
{
_someRandomText = value;
NotifyPropertyChanged("SomeRandomText");
}
}
To make code look cleaner, you can use attributes for INotifyPropertyChanged.
Easy usage of INotifyPropertyChanged with Property-Attribute
Have a look at this Use of Attributes... INotifyPropertyChanged
Actually you can, but you basically need to change the bytecode post C# compiler.
This may sound like a lot of work, but this is one of the easier postprocessing steps that for example PostSharp includes.
http://www.sharpcrafters.com/solutions/notifypropertychanged
http://www.sharpcrafters.com/blog/post/Recording-Automate-INotifyPropertyChanged-with-Karol-Waledzik-from-Internetium.aspx
A lot more functionality is available ;)
Otherwise note that
enter code hereenter code here`NotifyPropertyChanged("SomeRandomTextBeingNotified");
is bad code. I do all that in one field update method:
set
{
OnUpateField (ref _someRandomText, value);
}
The update method does all - check for equality (you do NOT want to trigger when new value = old value), then trigger updates as needed. It gets the property name through the calling method third parameter that is automatically set by the compiler. Alternatives are using a LINQ statement ( ref someRandomText, value, this->SomeRandomText). I never would love a string there that does not get renamed on refactoring ;)
If you don't have a base class, something like this is cake and very flexible:
public class NotificationObject : INotifyPropertChanged
{
private readonly Dictionary<string, object> Properties = new Dictionary<string, object>();
public event PropertyChangedEventHandler PropertyChanged;
protected TType Get<TType>(string propertyName)
{
object value;
return Properties.TryGetValue(propertyName, out value) ? (TType)value : default(TType);
}
protected void Set<TType>(TType value, string propertyName, params string[] dependantPropertyNames)
{
Properties[propertyName] = value;
OnPropertyChanged(propertyName);
if (dependantPropertyNames != null)
{
foreach (string dependantPropertyName in dependantPropertyNames)
{
OnPropertyChanged(dependantPropertyName);
}
}
}
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArts(propertyName));
}
}
}
This can be used like this:
public SomeObjectThatNeedsToNotifySomething : NotificationObject
{
public int SomeValue
{
get { return Get<int>("SomeValue"); }
set { Set<int>(value, "SomeValue", "SomeAggregateValue"); }
}
public int SomeOtherValue
{
get { return Get<int>("SomeOtherValue"); }
set { Set<int>(value, "SomeOtherValue", "SomeAggregateValue"); }
}
public int SomeAggregateValue
{
get { return SomeValue + SomeOtherValue; }
}
}
If you already have a base class and need to just implement the INotifyPropertyChanged interface, #Rob is correct, provide a backing field and fire the event.
There is no such thing as semi-automatic properties. Nevertheless, there are quite a few ways to implement INotifyPropertyChanged that don't require the burdensome imperative code.
1) Mentioned before: PostSharp, an aspect oriented and commercial project.
2) Creating a Castle DynamicProxy solution. A sample can be found here, actually there's plenty of others out there.
It's worthwhile investing some time in a generic solution, the boilerplate code can get vexing after a while and is prone to errors.
In classes whose instances I persist using an object database, I keep having to do this:
private string _name;
public string Name
{
get { return this._name; }
set { _name = value; this.Save(); }
}
whereas I would much rather type this:
[PersistedProperty(Name)]
private string _name;
where the PersistedProperty attributes generates a Getter and Setter just like the default [Property()] attribute, except I want to add a line of code to the generated Setter.
Is there a way I can create an attribute which does this? Hopefully , which works with Intellisense.
How does the default [Property()] attribute even do it's stuff? If I saw the code I could graft that...
Note: I am actually doing this in Boo, but thought I'd give c# code as more people might be willing to answer that, however, if there is a Boo specific solution, I'm all ears!
Update:
My aim was simply to reduce typing and clutter. It turns out the simplest way of doing this was with a script which generates partial classes based on markup in my classes.
Auto-generating source code from markup (in tandem with partial classes) is easy, and actually looks like an extremely promising way to get round some of the problems we normally try to solve with inheritance and generic types.
This requires aspect oriented programming. While not directly supported in .NET, it can be done via third party tooling, such as PostSharp.
For intellisense to work, however, this must be done in a library, as the (final) compiled code will be unrolled into the full property getter/setter.
Not easy to implement using attributes IMO.
Maybe you could use another approach, such as an extension method:
// Extension method that allows updating a property
// and calling .Save() in a single line of code.
public static class ISaveableExtensions
{
public static void UpdateAndSave<T>(
this ISaveable instance,
Expression<Func<T>> propertyExpression, T newValue)
{
// Gets the property name
string propertyName = ((MemberExpression)propertyExpression.Body).Member.Name;
// Updates its value
PropertyInfo prop = instance.GetType().GetProperty(propertyName);
prop.SetValue(instance, newValue, null);
// Now call Save
instance.Save();
}
}
...
// Some interface that implements the Save method
public interface ISaveable
{
void Save();
}
...
// Test class
public class Foo : ISaveable
{
public string Property { get; set; }
public void Save()
{
// Some stuff here
Console.WriteLine("Saving");
}
public override string ToString()
{
return this.Property;
}
}
...
public class Program
{
private static void Main(string[] args)
{
Foo d = new Foo();
// Updates the property with a new value, and automatically call Save
d.UpdateAndSave(() => d.Property, "newValue");
Console.WriteLine(d);
Console.ReadKey();
}
}
It's type-safe, autocompletion-friendly, but it requires more code than just .Save() in all setters, so not sure I would use it actually...
I'm working on some code where there is lots of code like this:
private int x;
public void SetX(int new_x)
{
this.SetXValue(new_x);
}
private void SetXValue(int new_x)
{
this.x = new_x;
}
and similarly with properties:
private int x;
public int X
{
get { return this.GetX(); }
}
private int GetX()
{
return this.x;
}
What i don't get is why the need for the private methods which do the actual work, i.e. why not just have methods like this instead:
public void SetX(int new_x)
{
this.x = new_x;
}
public int X
{
get { return this.x; }
}
is it just the other persons personal choice or is there some good reason for using the first way?
(i typed above code manually so sorry if any mistakes but you should hopefully see what i'm trying to say)
Cheers
A
There's no reason for code like that as far as I can see. If you're not doing anything with the new values (like processing/checking before storing) and you're writing C# 3.0 you can actually just shorthand it it to this:
public int MyProperty { get; set; }
The compiler creates the backing store for you and you can just reference:
this.MyProperty
...inside your class. You can also create get-only properties like:
public int MyProperty { get; private set; }
All of which I think is pretty neat!
Why don't you use the Getters and Setters directly to implement your logic? I don't understand the need for additional methods unless you have extra parameters that influence the setter's behavior:
private int myVar;
public int MyProperty
{
get
{
return myVar;
}
set
{
myVar = value;
}
}
public void SetMyPropertySpecial(int a, string reason)
{
Console.WriteLine("MyProperty was changed because of " + reason);
this.myVar = a;
}
Update:
Indeed, this person seems to like having more lines of code, but the structure is utterly useless. Stick to .NET standards using Getters and Setters (see MSDN)
No, there is no reason for doing this, it looks liks someone was paid by lines of code.
So, yes, you're right, this is just the other persons personal choice, and it's not a very good one.
A general rule of thumb is to use properties for simple get/set operations and get/set methods when there is a relevant part of logic needed to get/set a value (e.g. validation during set or database access during get).
So if the actual code is really as simple as in your example just use properties and do the work in their getters/setters.
If the actual code is more complex replace the properties (at least the setters) by methods as in your third example.
One possible reason would be that the properties can have login that should be executed only when the property is set externally and calls from inside the class do not execute the whole logic but only the logic in the private method. Of course it makes no sense to make these methods in advance because introducing them later will not change the contract of the class. Chances are that whoever wrote this code was new to C# and did not understand what properties do.
I think it must be an old Java developper that did this.
The .Net way is
private int _foo;
public int Foo
{
get
{
return _foo;
}
set
{
_foo = value;
dostuff();
}
}
That's very bizarre, there's no justifiable reason for doing that. Please refactor that code. There's also no need for a SetX method as setter can be included in properties. e.g.:
public int X {get; set;}
i may be missing something here, but this looks a bit mad to me!
You can achieve the same by either using automatic properties or properties with backing fields. here's a good description of both: http://weblogs.asp.net/dwahlin/archive/2007/12/04/c-3-0-features-automatic-properties.aspx
Yes, that is fine only if the SetValue is private or protected and is doing more than just setting a value.
I am working on a project where we do a lot of those things. That is because we are doing more than just setting a value (value checks, state checks etc.)
Having a public setter and a public SetValue does not make sense at all and will confuse your consumers as to what setter to use.
Here is another scenario where we use this kind of design:
public abstract class A{
protected virtual void SetValue(object value);
public object SomeObject{
set{SetValue(value);}
}
}
In this case, we want class A to delegate setting/checking that value to whatever class inheriting from it.
I am using a class that I cannot edit, it has a property (a boolean) of which it would be nice to be informed when it changes, I can't edit the properties get or set as I am importing the class from a .dll (which I don't have the code for).
How do I create an event/function that is fired when the property is changed?
Additional
It is only changed within its own class, directly to the underlying private variable.
E.g.
private bool m_MyValue = false;
public bool MyValue
{
get { return m_MyValue; }
}
private void SomeFunction()
{
m_MyValue = true;
}
You can't, basically... not without using something like the debugger API to inject code at execution time and modifying the IL of the original library (and I'm not recommending either of those solutions; aside from anything else it may violate the licence of the library).
Basically if a property doesn't support notification, it doesn't support notification. You should look for a different way of approaching your problem. (Would polling work, for example?)
You cant do this directly [as Jon Skeet said], unless it's virtual, you're in a position to intercept all instance creations of the class and there are no changes to a backing field that influences the real 'value' of the propget.
The only way to brute force this is to use Mono.Cecil or MS CCI to instrument the prop setter a la this DimeCast on Cecil. (Or PostSharp)
However this wouldn't trap internal changes to the backing field (if there even is one). (Which is why wrapping probably wont work).
UPDATE: Given your update that you're definitely trying to trap the underlying field change, the only way to do that is to use PS / CCI / Cecil and analyse the flow to intercept all field updates. In short, not very feasible.
Arguably, the only real way to do this is to create some kind of "watcher" component, running in a separate thread, whose job is to read the property at intervals and raise an event when the property's value changes. Of course this solution sails in the murky waters of threading and synchronization.
On the assumption that your application is single-threaded in respect to this object, your cleanest solution is to make method calls to this object via a proxy object. It would have the job of checking the before and after state of the property and raising an event in the case it has changed.
Here's a simple example of what I'm talking about:
public class SomeProxy
{
public SomeProxy(ExternalObject obj)
{
_obj = obj;
}
public event EventArgs PropertyChanged;
private bool _lastValue;
private ExternalObject _obj;
protected virtual void OnPropertyChanged()
{
if(PropertyChanged != null)
PropertyChanged();
}
protected virtual void PreMethodCall()
{
_lastValue = _obj.SomeProperty;
}
protected virtual void PostMethodCall()
{
if(_lastValue != _obj.SomeProperty)
OnPropertyChanged();
}
// Proxy method.
public SomeMethod(int arg)
{
PreMethodCall();
_obj.SomeMethod(arg); // Call actual method.
PostMethodCall();
}
}
Obviously you can build this proxy pattern into a suitable object - you just have to be aware that all calls have to go through the proxy for the event to be raised when you expect it to be.
As previously mentioned, the most direct method (and that which requires the least change to code) is to use an AOP library such as PostSharp.
However, a solution can be achieved using traditional C#/.NET by using the dependency property pattern, used throughtout WPF to great effect. I suggest to read up on this, and consider implementing such a system (or at least a simplified version of it) for your project, if appropiate.
You will need to create a class that wraps the class in the dll, within the setter property just raise an event there using the normal methods.
Could you inherit from the class and hide the property? Something like this...
class MyClass : BaseClass
{
// hide base property.
public new bool MyProperty
{
get
{
return base.MyProperty;
}
set
{
base.MyProperty = value;
RaiseMyPropertyChangedEvent();
}
}
}
I think Alex' idea of a wrapper is good, however, given that the most important thing to you is that you know that the value is changed before use, you could simply move the notification to the getter, circumventing the worries of internal value change. That way you get something similar to polling, yet reliable:
class MyClass : BaseClass
{
//local value
private bool local;
//first access yet?
private bool accessed = false;
// Override base property.
public new bool MyProperty
{
get
{
if(!accessed)
{
// modify first-get case according to your taste, e.g.
local = base.MyProperty;
accessed = true;
RaiseMyPropertyChangedBeforeUseEvent();
}
else
{
if(local != base.MyProperty)
{
local = base.MyProperty;
RaiseMyPropertyChangedBeforeUseEvent();
}
}
return local;
}
set
{
base.MyProperty = value;
}
}
}
You can try to inherit it and use it's child instead of it.
Override the "set" of the property so it raises the event.
EDIT: ... only if property is virtual in the parent class ...