I am using Castle.DynamicProxy2 and I am instantiating my proxy as such:
private static T GenerateProxy()
{
ArrayList addtlInterfaces = new ArrayList();
addtlInterfaces.Add(typeof (INotifyPropertyChanged));
addtlInterfaces.Add(typeof (EntityStatus));
object entityProxy = ProxyGenerator.CreateClassProxy(typeof(T),
addtlInterfaces.ToArray(typeof(Type)) as Type[],
ProxyGenerationOptions.Default,
new IInterceptor[] { new LazyInterceptor() });
return (T)entityProxy;
}
My interface of IEntityStatus looks like such:
public interface IEntityStatus
{
bool IsDirty
{ get; set;}
}
I need to be able to use that property during run time so that when my DTO has a property changed event the event could set the DTO to dirty. However because it is an interface and has no explicit implementation I am at a loss as to how to do this. Creating a delegate for the get and set method is an option I would like to avoid. So is there another way to achieve what I am looking to achieve?
I realize I could set up a collection of all my active DTOs and when the property changed event fires on one of the DTOs I could update that collection to show that this particular DTO is dirty, but I would really like for this information to be a part of the proxied DTO for pure syntactic ease.
Look forward to responses!
I dont know how you handle the INotifyPropertyChanged but I'd use mixin for both interfaces, having one subscribed to another's event. Is that a viable solution?
Related
Considering a class with a large number of properties, I want to implement a Dirty flag (in order to know if I should update the value in the database).
Is there any way to raise PropertyChanged on All the properties without having to manually go through and pluck it in the setter?
Edit to clear up some things: I did go through the thread that was linked here, and found some things, but unfortunately they do not suit my need. I don't really need to send an event, I just need to flip a flag. Also, that thread is quite old, and I hoped that maybe with C# 7 something came out which would help with it, that I missed in the changelog.
Why don't I just go and do it manually? Well, I might have to. But I'd have to declare the "hidden" variables, manage the code myself, I hoped MS would've done something to help, maybe something like was suggested in the other topic
public Type Name {get; set; notify { () => IsDirty = true; }}
that would help a lot (ignoring the fact it would ask me to declare the get and set anyways because they're abstract.
Add a method that looks like this:
public void Test()
{
if(PropertyChanged != null)
PropertyChanged(new PropertyChangedEventArgs(null));
}
Passing a null or empty string as the property name tells consumers that all properties have been changed.
https://msdn.microsoft.com/en-us/library/system.componentmodel.propertychangedeventargs.propertyname(v=vs.110).aspx
You can but its also a lot of work. Make an Attribute and use it on those properties. in the base class of your ViewModel,
which will implement INotifyPropertyChanged,
You register in its Constructor to the PropertyChanged event and check via reflection if the property that changed has your attribute on it,
and then set IsDirty accordingly.
I am trying to implement a very simple and more importantly optional object tracking system similar to how entity framework tracks object changes (How change tracking works in Entity Framework).
I have a base class that all other objects inherit from. This class has 1 boolean field called modified. The explicit solution to this is to update every setter on all properties of other classes to set modified = true when the setter is triggered. This solution has been presented in detail here Create an event to watch for a change of variable.
I want a more implicit solution to this. I have a lot of objects and a LOT of properties. Updating the setter is incredibly messy. I don't want to directly mimmic how entity framework does things because it is too expensive for my current requirements. I want a list of objects that i can loop to check of modified == true. This allows me to optionally track object and quickly check if they have changed without having to trigger an update for each individual object. Is there a way that i can set some sort of listener on all of the property getter and setters implicitly?
I know this code doesnt exist, but does .NET have a way to monitor the object to see if it has changed.
[OnChange=ObjectChanged()] //maybe this way
public class MyClass
{
bool modified {get; set;}
public MyClass() : OnChange(ObjectChanged) //or this way
{
}
private void ObjectChanged()
{
modified = true;
}
}
As i mentioned, i dont want to update every setter or copy what entity framework does.
There's nothing built-in in the .NET framework for this, but there are third-party tools to do exactly that.
One such option would be Fody/PropertyChanged, which injects OnPropertyChanged calls into all automatic property setters of your classes. You can subscribe to the PropertyChanged event and update your Boolean flag. As an additional bonus, (a) you get the name of the property that changed and (b) other classes (e.g. your UI framework) can subscribe to the event as well.
In the context of the MVVM pattern, how would one structure the ViewModel when Models do not implement the INotifyPropertyChanged interface?
I like to keep my Models as simple as possibile and implementing the INotifyPropertyChanged interface only for binding purposes seems like unwanted complexity. That's why most of the times i require my VMs to wrap model properties like in the following example:
class ViewModel : INotifyPropertyChanged
{
private Model model;
public int MyProperty
{
get { return model.MyProperty; }
set
{
if (value != model.MyProperty)
{
model.MyProperty = value;
// Trigger the PropertyChanged event
OnPropertyChanged("MyProperty");
}
}
}
/* ... */
}
This will make bindings work ok, including two-way ones.
Now, what would happen if a command executes a model method with complex logic (affecting the value of many properties of different objects)? The model is not implementing INotifyPropertyChanged so there's no way we can know it was updated. The only solution that comes to my mind is to use messaging (mediator pattern) to inform all VMs of the execution of the method so that each VM fires the PropertyChanged event for each potentially affected property:
// Sample ICommand.Execute() implementation
public void Execute(object parameter)
{
var model = (Model)parameter;
model.VeryComplexMethod();
// Just an example, the string "VeryComplexMethodExecuted" is
// sent to all listening VMs. Those VMs will in turn fire the
// PropertyChanged event for each property that may have changed
// due to the execution of the complex model method.
Messaging.Broadcast("VeryComplexMethodExecuted");
}
Please share your ideas, thanks.
Declare your members virtual and use something like Castle Dynamic Proxy to inject change notification automatically:
http://ayende.com/blog/4106/nhibernate-inotifypropertychanged
This has to be used with care when your models are being created in your data layer because it returns a new instance entirely. Your database code will think the object has changed and serialize it back out again which will in turn have a huge impact on performance. Fortunately all the good ORMs provide mechanisms for you to substitute in class wrappers at creation time.
I have a class property that looks as follows:
public List<Recipe> RecipeList
{
get { return this._recipeList; }
set
{
this._recipeList = value;
OnPropertyChanged("RecipeList");
}
}
In another method I have the following which references the property above.
private void RecipeSearch()
{
this.RecipeList = RecipeManagerService.SearchByUnit(SearchCriteria)
.Where(recipe => recipe.IsApproved == true && !recipe.IsHidden).ToList();
}
Code Analysis is issuing a CA 2227 warning: Change RecipeList to be read-only by removing the setter. Could anyone tell me why?
Adding a public setter on a List<T> object is dangerous. You can eliminate this warning by making your setter private:
public List<Recipe> RecipeList
{
get { return this._recipeList; }
private set
{
this._recipeList = value;
OnPropertyChanged("RecipeList");
}
}
This will still allow your class to change this method, but no external source.
I think it's suggesting that usually collection properties themselves shouldn't be mutable - it's more common for the collection to be mutable, and just available via a setter.
It's only a suggestion though :)
In this case you'd use:
RecipeList.Clear();
RecipeList.AddRange(RecipeManagerService
.SearchByUnit(SearchCriteria)
.Where(r => r.IsApproved && !r.IsHidden));
Note that this won't fire the change event though... you might want to use ObservableCollection instead.
This will also mean that anyone can change the contents of the recipe list... do you definitely want that? Another alternative is to expose a ReadOnlyCollection<T> property or something like that, and only make changes within your own class. It really depends what you're trying to do though.
Do you want another instance messing with RecipeList? Generally, I don't let anything change my collection instances except the instance that owns the collection. You could make it private.
The MSDN description is fairly clear:
A writable collection property allows
a user to replace the collection with
a completely different collection
It wouldn't be good OO if the client of your class could change the list to be a completely different list of Recipes. That is against encapsulation.
Ensuring the clients just add or remove items is what you probably want to do.
I don't think there's anything illegal about the code, but it's common practice to have no public setter for collection type properties. Your private RecipeSearch method should just set _recipeList and raise the event, or you could make _recipeList itself a protected property that handles the event.
Allowing the list property to be mutated in two ways (via it's own Add and Remove methods and the list instance as a whole) creates an ambiguous interface to those who consume that property. This confuses responsibilities and creates a larger technical debt/maintenance overhead.
Instead, it is often better practise to separate these concerns so that the property provides access to a single instance of the list. If the list instance must be changeable, a separate mechanism for doing so makes it much clearer that the action of interacting with the property and the action of changing which list instance that property points to are distinct.
I'm looking for a clean and elegant solution to handle the INotifyPropertyChanged event of nested (child) objects. Example code:
public class Person : INotifyPropertyChanged {
private string _firstName;
private int _age;
private Person _bestFriend;
public string FirstName {
get { return _firstName; }
set {
// Short implementation for simplicity reasons
_firstName = value;
RaisePropertyChanged("FirstName");
}
}
public int Age {
get { return _age; }
set {
// Short implementation for simplicity reasons
_age = value;
RaisePropertyChanged("Age");
}
}
public Person BestFriend {
get { return _bestFriend; }
set {
// - Unsubscribe from _bestFriend's INotifyPropertyChanged Event
// if not null
_bestFriend = value;
RaisePropertyChanged("BestFriend");
// - Subscribe to _bestFriend's INotifyPropertyChanged Event if not null
// - When _bestFriend's INotifyPropertyChanged Event is fired, i'd like
// to have the RaisePropertyChanged("BestFriend") method invoked
// - Also, I guess some kind of *weak* event handler is required
// if a Person instance i beeing destroyed
}
}
// **INotifyPropertyChanged implementation**
// Implementation of RaisePropertyChanged method
}
Focus on the BestFriend Property and it's value setter. Now I know that I could do this manually, implementing all steps described in the comments. But this is going to be a lot of code, especially when I'm planning to have many child properties implementing INotifyPropertyChanged like this. Of course they are not going to be always of same Type, the only thing they have in common is the INotifyPropertyChanged interface.
The reason is, that in my real scenario, I have a complex "Item" (in cart) object which has nested object properties over several layers (Item is having a "License" object, which can itself have child objects again) and I need to get notified about any single change of the "Item" to be able to recalculate the price.
Do you some good tips or even some
implementation to help me to solve
this?
Unfortunately, I'm not able/allowed to use post-build steps like PostSharp to accomplish my goal.
since I wasn't able to find a ready-to-use solution, I've done a custom implementation based on Pieters (and Marks) suggestions (thanks!).
Using the classes, you will be notified about any change in a deep object tree, this works for any INotifyPropertyChanged implementing Types and INotifyCollectionChanged* implementing collections (Obviously, I'm using the ObservableCollection for that).
I hope this turned out to be a quite clean and elegant solution, it's not fully tested though and there is room for enhancements. It's pretty easy to use, just create an instance of ChangeListener using it's static Create method and passing your INotifyPropertyChanged:
var listener = ChangeListener.Create(myViewModel);
listener.PropertyChanged +=
new PropertyChangedEventHandler(listener_PropertyChanged);
the PropertyChangedEventArgs provide a PropertyName which will be always the full "path" of your Objects. For example, if you change your Persons's "BestFriend" Name, the PropertyName will be "BestFriend.Name", if the BestFriend has a collection of Children and you change it's Age, the value will be "BestFriend.Children[].Age" and so on. Don't forget to Dispose when your object is destroyed, then it will (hopefully) completely unsubscribe from all event listeners.
It compiles in .NET (Tested in 4) and Silverlight (Tested in 4). Because the code in seperated in three classes, I've posted the code to gist 705450 where you can grab it all: https://gist.github.com/705450 **
*) One reason that the code is working is that the ObservableCollection also implements INotifyPropertyChanged, else it wouldn't work as desired, this is a known caveat
**) Use for free, released under MIT License
I think what you're looking for is something like WPF binding.
How INotifyPropertyChanged works is that the RaisePropertyChanged("BestFriend"); must only be fored when the property BestFriend changes. Not when anything on the object itself changes.
How you would implement this is by a two step INotifyPropertyChanged event handler. Your listener would register on the changed event of the Person. When the BestFriend gets set/changed, you register on the changed event of the BestFriend Person. Then, you start listening on changed events of that object.
This is exactly how WPF binding implements this. The listening to changes of nested objects is done through that system.
The reason this is not going to work when you implement it in Person is that the levels can become very deep and the changed event of BestFriend does not mean anything anymore ("what has changed?"). This problem gets larger when you have circular relations where e.g. the best friend of your monther is the mother of your best fiend. Then, when one of the properties change, you get a stack overflow.
So, how you would solve this is to create a class with which you can build listeners. You would for example build a listener on BestFriend.FirstName. That class would then put an event handler on the changed event of Person and listen to changes on BestFriend. Then, when that changes, it puts a listener on BestFriend and listens for changes of FirstName. Then, when that changes, it sends raises an event and you can then listen to that. That's basically how WPF binding works.
See http://msdn.microsoft.com/en-us/library/ms750413.aspx for more information on WPF binding.
Interesting solution Thomas.
I found another solution. It's called Propagator design pattern. You can find more on the web (e.g. on CodeProject: Propagator in C# - An Alternative to the Observer Design Pattern).
Basically, it's a pattern for updating objects in a dependency network. It is very useful when state changes need to be pushed through a network of objects. A state change is represented by an object itself which travels through the network of Propagators. By encapsulating the state change as an object, the Propagators become loosely coupled.
A class diagram of the re-usable Propagator classes:
Read more on CodeProject.
I have been Searching the Web for one day now and I found another nice solution from Sacha Barber:
http://www.codeproject.com/Articles/166530/A-Chained-Property-Observer
He created weak references within a Chained Property Observer. Checkout the Article if you want to see another great way to implement this feature.
And I also want to mention a nice implementation with the Reactive Extensions #
http://www.rowanbeach.com/rowan-beach-blog/a-system-reactive-property-change-observer/
This Solution work only for one Level of Observer, not a full Chain of Observers.
I wrote an easy helper to do this. You just call BubblePropertyChanged(x => x.BestFriend) in your parent view model. n.b. there is an assumption you have a method called NotifyPropertyChagned in your parent, but you can adapt that.
/// <summary>
/// Bubbles up property changed events from a child viewmodel that implements {INotifyPropertyChanged} to the parent keeping
/// the naming hierarchy in place.
/// This is useful for nested view models.
/// </summary>
/// <param name="property">Child property that is a viewmodel implementing INotifyPropertyChanged.</param>
/// <returns></returns>
public IDisposable BubblePropertyChanged(Expression<Func<INotifyPropertyChanged>> property)
{
// This step is relatively expensive but only called once during setup.
MemberExpression body = (MemberExpression)property.Body;
var prefix = body.Member.Name + ".";
INotifyPropertyChanged child = property.Compile().Invoke();
PropertyChangedEventHandler handler = (sender, e) =>
{
this.NotifyPropertyChanged(prefix + e.PropertyName);
};
child.PropertyChanged += handler;
return Disposable.Create(() => { child.PropertyChanged -= handler; });
}
Check-out my solution on CodeProject:
http://www.codeproject.com/Articles/775831/INotifyPropertyChanged-propagator
It does exactly what you need - helps to propagate (in elegant way) dependent properties when relevant dependencies in this or any nested view models change:
public decimal ExchTotalPrice
{
get
{
RaiseMeWhen(this, has => has.Changed(_ => _.TotalPrice));
RaiseMeWhen(ExchangeRate, has => has.Changed(_ => _.Rate));
return TotalPrice * ExchangeRate.Rate;
}
}
Please take a look at EverCodo.ChangesMonitoring. This is a framework to handle PropertyChanged and CollectionChanged events on arbitrary hierarchy of nested objects and collections.
Create a monitor to handle all change events of the object tree:
_ChangesMonitor = ChangesMonitor.Create(Root);
_ChangesMonitor.Changed += ChangesMonitor_Changed;
Do arbitrary modifications on the object tree (all of them will be handled):
Root.Children[5].Children[3].Children[1].Metadata.Tags.Add("Some tag");
Root.Children[5].Children[3].Metadata = new Metadata();
Root.Children[5].Children[3].Metadata.Description = "Some description";
Root.Children[5].Name = "Some name";
Root.Children[5].Children = new ObservableCollection<Entity>();
Handle all events in one place:
private void ChangesMonitor_Changed(object sender, MonitoredObjectChangedEventArgs args)
{
// inspect args parameter for detailed information about the event
}