Last day I ended up thinking about some collections interdependence.
I cannot put a better label, name, title, or whatever suggesting this situation... so feel free to suggest anything better than my cheap labeling, that is " Interdependent Collections Modifications Management".
Long story short, the example below.
First, let's consider a couple of classes:
public class DummyItem
{
public DummyItem(String name)
{
this.Name = name;
}
public String Name { get; set; }
}
// A kind of repository of DummyItems
public class BusinessClassProvider
{
public BusinessClassProvider()
{
this.Collection = new List<DummyItem>();
}
public IList<DummyItem> DummyItems{ get; private set; }
}
public class BusinessClassConsumer
{
public BusinessClassConsumer()
{
this.Collection = new Collection<DummyItem>();
}
public ICollection<DummyItem> DummItems{ get; private set; }
}
Now let's say that BusinessClassProvider.Collection is populated via some processes, user inputs, etc.
The BusinessClassConsumer Collection is something selected from BusinessClassProvider Collection by let's say also some user inputs or any other way.
Now if I remove or add a DummyItem from the BusinessClassProvider Collection I need to create Additional Nethods to wrap or eventually if they are some events supported to notify the others of what have been changed and remove accordingly the related other Collections (e.g. BusinessClassConsumer one) to also remove this item.
Basically it means a lot of boilerplate code and a lot of stuff to handle manually.
Of course, we could go with another strategy using IEnumerable as BusinessClassConsumer Collection but it does not provide the same options about indexing for instance, furthermore it forces to iterate over and over on BusinessClassProvider Collection.
I know it raises many more questions like which collection is kinda the provider and the others which consumes from.
Is there any frameworks via Attributes, or any other nasty tricks to enforce the dependency between several collections?
By the way, once again, is there anybody who knows how to label correctly this sort of situation?
If your need is to be notified when a collection change (item added, removed or the whole collection refreshed) you might want to use an ObservableCollection.
It's used mostly in WPF to notify the UI when a collection of item has changed and needs to be refreshed.
If your need is a producer/consumer collection, you might want to look for a BlockingCollection.
It's a thread safe collection that do all the producer/consumer things for you.
Yes, there are. Quite a few actually, but ObservableCollection that come with .net are not preferred. Instead one would use Rx-Linq(Reactive extension) that adds observables, Linq and schedulers together.
Related
In DDD it is customary to protect an entity's properties like this:
public class Customer
{
private Customer() { }
public Customer(int id, string name) { /* ...populate properties... */ }
public int Id { get; private set; }
public string Name { get; private set; }
// and so on...
}
EF uses reflection so it can handle all those privates.
But what if you need to attach an entity without loading it (a very common thing to do):
var customer = new Customer { Id = getIdFromSomewhere() }; // can't do this!
myContext.Set<Customer>().Attach(customer);
This won't work because the Id setter is private.
What is a good way to deal with this mismatch between the language and DDD?
Ideas:
make Id public (and break DDD)
create a constructor/method to populate a dummy object (makes no sense)
use reflection ("cheat")
???
I think the best compromise, is to use reflection, and set that private Id property, just like EF does. Yes it's reflection and slow, but much faster than loading from the database. And yes it's cheating, but at least as far as the domain is concerned, there is officially no way to instantiate that entity without going through the constructor.
How do you handle this scenario?
PS I did a simple benchmark and it takes about 10s to create a million instances using reflection. So compared to hitting the database, or the reflection performed by EF, the extra overhead is tiny.
"customary" implicitly means it's not a hard set rule, so if you have specific reasons to break those rules in your application, go for it. Making the property setter public would be better than going into reflection for this: not only because of performance issues, but also because it makes it much easier to put unwanted side-effects in your application. Reflection just isn't the way to deal with this.
But I think the first question here is why you would want the ID of an object to be set from the outside in the first place. EF uses the ID primarily to identify objects and you should not use the ID for other logic in your application than just that.
Assuming you have a strong reason to want to change the ID, I actually think you gave the answer yourself in the source you just put in the comments:
So you would have methods to control what happens to your objects and
in doing so, constrain the properties so that they are not exposed to
be set or modified “willy nilly”.
You can keep the private setter and use a method to set the ID.
EDIT:
After reading this I tried doing some more testing myself and you could have the following:
public class Customer
{
private Customer() { }
public Customer(int id) { /* only sets id */ }
public Customer(int id, string name) { /* ...populate properties... */ }
public int Id { get; private set; }
public string Name { get; private set; }
// and so on...
public void SetName(string name)
{
//set name, perhaps check for condition first
}
}
public class MyController
{
//...
var customer = new Customer(getIdFromSomewhere());
myContext.Set<Customer>().Attach(customer);
order.setCustomer(customer);
myContext.SaveChanges(); //sets the customer to order and saves it, without actually changing customer: still read as unchanged.
//...
}
This code leaves the private setters as they were (you will need the methods for editing of course) and only the required changes are pushed to the db afterwards. As is also explained in the link above, only changes made after attaching are used and you should make sure you don't manually set the state of the object to modified, else all properties are pushed (potentially emptying your object).
This is what I'm doing, using reflection. I think it's the best bad option.
var customer = CreateInstanceFromPrivateConstructor<Customer>();
SetPrivateProperty(p=>p.ID, customer, 10);
myContext.Set<Customer>().Attach(customer);
//...and all the above was just for this:
order.setCustomer(customer);
myContext.SaveChanges();
The implementations of those two reflection methods aren't important. What is important:
EF uses reflection for lots of stuff
Database reads are much slower than these reflection calls (the benchmark I mentioned in the question shows how insignificant this perf hit is, about 10s to create a million instances)
Domain is fully DDD - you can't create an entity in a weird state, or create one without going through the constructor (I did that above but I cheated for a specific case, just like EF does)
Here is the PostSharp support discussion (titled: "NotifyPropertyChanged and ObservableCollection") that sparked my initial confusion on this topic. Further explanation is in the answer I posted (not 100% confident in my answer).
I'm a little confused on how PostSharp's [NotifyPropertyChanged] aspect affects a class's collection properties (if at all), and whether I need to be using an ObservableCollection<> or AdvisableCollection<>. If I understand correctly, if I want notifications from the collection, I MUST change it to at least an ObservableCollection<>, correct? The [NotifyPropertyChanged] aspect doesn't magically make whatever collection types are in the class observable.
If that's the case, then when would I use ObservableCollection<> or AdvisableCollection<>? Should AdvisableCollection<> be reserved for when I need the aggregation pattern applied by PostSharp? Or should I just always use AdvisableCollection<> whenever applying PostSharp's [NotifyPropertyChanged] attribute?
[NotifyPropertyChanged]
public class Test {
public int PropVal { get; set; }
public List<string> PropCollection { get; set; } //Should this be ObservableCollection
//or AdvisableCollection?
}
Congratulations on the Tumbleweed badge and many apologies for the delayed answer.
Collections are currently not well integrated with the aspect in sense that there is a bit of work needed for real-life examples to work properly. Let me explain few key steps:
[AggregateAllChanges] instructs the runtime that it should relay any change observed on the collection as a change of the property itself. This in particular means that a virtual Item[] dependency is created (which is used by a "standard" collections to notify change of collection shallow "state").
In reality properties working with collections content are usually aggregates in some sense, depending not only on set of items stored in the collection but also on state of individual objects in the collection. Currently there is no way to express that and/or selectively relay these changes. For this you need to create a class derived from ObservableCollection<T> that looks like following:
[NotifyPropertyChanged]
public class ObservableCollectionEx<T> : ObservableCollection<T>
{
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (T item in e.OldItems)
{
((INotifyPropertyChanged)item).PropertyChanged -= OnItemPropertyChanged;
}
}
else if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (T item in e.NewItems)
{
((INotifyPropertyChanged)item).PropertyChanged += OnItemPropertyChanged;
}
}
base.OnCollectionChanged(e);
}
protected void OnPropertyChanged(string propertyName)
{
base.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
protected void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
NotifyPropertyChangedServices.SignalPropertyChanged(this, "Item[]");
NotifyCollectionChangedEventArgs collectionChangedEventArgs = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
base.OnCollectionChanged(collectionChangedEventArgs);
}
}
The above does exactly what is needed - when anything changes on any object within the collection, collection reports that it itself had changed.
Now in a class it would look like this:
[NotifyPropertyChanged]
public class TestClass
{
[AggregateAllChanges]
public ObservableCollectionEx<TestItem> Items { get; } = new ObservableCollectionEx<TestItem>();
[SafeForDependencyAnalysis]
public int Sum
{
get
{
if (Depends.Guard)
{
Depends.On(this.Items);
}
return this.Items.Sum(x => x.Value);
}
}
}
[NotifyPropertyChanged]
public class TestItem
{
public int Value { get; set; }
}
The above is not ideal performance-wise if there are other properties on the TestItem class that are frequently changed. In that case, one may consider to add a some kind of filtering to ObservableCollectionEx.
Regarding AdvisableCollection<T> you are right - while it can be used, it's main purpose is different.
Well, after receiving the "Tumbleweed" badge on this question (not intended, but funny... better than downvotes), I've spent some more time trying to sort out/better define my confusion and coalesce my own answer from the chaos...
The PostSharp support discussion (titled: "NotifyPropertyChanged and ObservableCollection") that sparked my initial confusion mentions two things:
-Support for intercepting changes in ObservableCollection<> was added in 4.2.
-To raise the PropertyChanged event on each collection change, the collection must be marked with [AggregateAllChanges].
So it would seem PostSharp's NotifyPropertyChanged aspect supports at least ObservableCollection<> if the [AggregateAllChanges] attribute is applied. However, a subsequent conversation on the PostSharp site's chat feature yielded:
-"You need to use collection classes defined by PostSharp to have reliable support for NotifyPropertyChanged aspect. See Working With Collections" (which mentions the Aggregatable pattern).
-After reading the provided documentation, the conclusion seems to be that I need to use AdvisableCollection<> (a PostSharp-defined collection) instead, but the examples all seem to be in the context of the Aggregatable pattern, with parent-child relationships, etc. Hence my confusion. I'm not trying to set up parent-child relationships, just trying to get NotifyPropertyChange on collections.
Next is another support discussion that demonstrates using NotifyPropertyChanged with a non-PostSharp-defined collection, applying [AggregateAllChanges] to a BindingList<>.
-In this instance, BindingList<> did not have one of the events that NotifyPropertyChanged expected, so this had to be wired up manually with NotifyPropertyChangedServices.
For a bit more background, I read this PostSharp blog post that gets into the Aggregation and Composition patterns.
Trying to boil everything down, my (possibly incorrect) conclusion is:
-[AggregateAllChanges] applied to non-PostSharp-defined collections (ObservableCollection<>, BindingList<>) is effectively an opt-in to the NotifyPropertyChanged aspect, with the caveat that the collection you apply it to (ex. BindingList<>) may not support all of the events the aspect expects, requiring you to wire up the PropertyChanged notification yourself via NotifyPropertyChangedServices.
-AdvisableCollection<> implements INotifyPropertyChanged as well as INotifyCollectionChanged (as does ObservableCollection<>), can be used in place of standard .net collections (not BindingList<> though... different interfaces), and would still require [AggregateAllChanges] to raise PropertyChanged notifications. Otherwise, the purpose of AdvisableCollection<> is to allow injection of behaviors related to the Aggregatable pattern.
If anyone has corrections to these assumptions, please feel free :) I will gladly mark a clearer/better explanation as the answer.
I have a class with about 20 properties but I'd simplify it for this question:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
I'd like to have a class or property that identifies whether my class is dirty. By this I mean to identify whether any of its values have changed?
There are 3 design approaches I can take:
1)
When setting the property inside the class, I check whether the property IsDirty.
public string Name
{
get { return this._name; }
set { if (this._name != value) { this.IsDirty = true; this._name = value; }
}
2)
When setting the property from outside the class, I check whether the property IsDirty.
e.g.
if (p.Name != newName)
{
p.IsDirty = true;
p.Name = newName;
}
This approach forces me to add lots of ifs in the client class. Some properties are even collections or even reference objects so the number of lines would be increased even.
3)
When the object is ready to be saved, then I check whether any properties IsDirty by getting a cloned object and checking the equality.
This would have a poorer performance as I would have to clone or load again the original object then compare the properties one by one.
Which one is the best design? or is there any other design pattern that can help with this?
Another option would be to Implement the INotifyPropertyChanged Interface.
Please note that this will help you make thing more tidy and your API clearer, but as far as internal implementation regarding keeping track after changes, It is still up to you to implement. I think this goes along best with your Option #1
Option 1 is clearly best: it puts the responsibility of tracking dirtiness where it belongs: inside the object. Option 2 is out because as you mentioned, you are forcing this responsibility onto the clients of your classes. And option 3 has the additional problem as you mentioned of performance.
Incidentally, you should look into a proxy implementation using DynamicProxy. This will allow your code to look like this:
public class Product
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
and with the judicious use of interceptors, you can get the behaviour you want. You can write an interceptor to intercept any "sets" and do some logic inside, such as setting an IsDirty flag.
Another idea would be to make this a GoF Observable and let interested Observer parties register their interest in changes. It's a more event-based approach.
This is the best solution and complies with SRP principle very nicely, I created the below classes:
ProductWithChangeDetection; this uses the Decorator pattern to add this new feature to an existing product object
ProductChangeDetector; this contains logics for checking and notification. Currently only exposes ChangeDetected property but if more complexity needed one should implement INotifyPropertyChange interface.
ProductEquitable; this implements IEquitable and has some overloads for checking whether two objects/properties are equal
I was wondering what is the recommended way to expose a collection within a class and if it is any different from the way of doing that same thing when working with NHibernate entities.
Let me explain... I never had a specific problem with my classes exposing collection properties like:
IList<SomeObjType> MyProperty { get; set; }
Having the setter as protected or private gives me some times a bit more control on how I want to handle the collection.
I recently came across this article by Davy Brion:
http://davybrion.com/blog/2009/10/stop-exposing-collections-already/
Davy, clearly recommends to have collections as IEnumerables instead of lets say Lists in order to disallow users of having the option to directly manipulate the contents of those collections. I can understand his point but I am not entirely convinced and by reading the comments on his post I am not the only one.
When it comes to NHibernate entities though, it makes much sense to hide the collections in the way he proposes especially when cascades are in place. I want to have complete control of an entity that is in session and its collections, and exposing AddXxx and RemoveXxx for collection properties makes much more sense to me.
The problem is how to do it?
If I have the entity's collections as IEnumerables I have no way of adding/removing elements to them without converting them to Lists by doing ToList() which makes a new list and therefore nothing can be persisted, or casting them to Lists which is a pain because of proxies and lazy loading.
The overall idea is to not allow an entity to be retrieved and have its collections manipulated (add.remove elements) directly but only through the methods I expose while honouring the cascades for collection persistence.
Your advice and ideas will be much appreciated.
How about...
private IList<string> _mappedProperty;
public IEnumerable<string> ExposedProperty
{
get { return _mappedProperty.AsEnumerable<string>(); }
}
public void Add(string value)
{
// Apply business rules, raise events, queue message, etc.
_mappedProperty.Add(value);
}
This solution is possible if you use NHibernate to map to the private field, ie. _mappedProperty. You can read more about how to do this in the access and naming strategies documentation here.
In fact, I prefer to map all my classes like this. Its better that the developer decides how to define the public interface of the class, not the ORM.
How about exposing them as ReadOnlyCollection?
IList<SomeObjType> _mappedProperty;
return new ReadOnlyCollection<SomeObjType> ExposedProperty
{
get
{
return new ReadOnlyCollection(_mappedProperty);
}
}
I am using NHibernate and I usually keep the collections as ISet and make the setter protected.
ISet<SomeObjType> MyProperty { get; protected set; }
I also provide the AddXxx and RemoveXxx for collection properties where they are required. This has worked quite satisfactorily for me most of the time. But I will say that there have been instances where it had made sense to allow client code add items to the collection directly.
Basically, what I have seen is if I follow the principle of "Tell, Don't Ask" in my client code, without worrying too much about enforcing rigid access constraints on my Domain Object properties, then I always end up with a good design.
I can't find any idea of the way to use this attribute?
MSDN indicates it is indeed to indicate that a property editor can be reused without needing to recreate each time.
This is a performance win, especially if your editor needs to do significant work on start up which can be avoided. Unless you are actually having performance issues then I wouldn't worry about it.
imagine you have scenario like this:
class Complex
{
public OtherComplex1 Property1 { get; set; }
public OtherComplex2 Property2 { get; set; }
public OtherComplex2 Property3 { get; set; }
.....
public OtherComplexN PropertyN { get; set; }
}
each of your properties has its own type designer, which displays some properties, etc.
say, you have two different instances of the Complex class + instance of some other arbitrary class.
now, when you toggle between your objects like this - complex instance 1 -> other -> complex instance 2 - everything will work fine, but if you do something like this:
complex instance 1 -> complex instance 2, you'd notice that properties are not beeing refreshed.
that is default behavior of property grid, which tries to optimize number of data refresh operations. unless you want to bake a lot of logic in order to keep your designers updated, i'd suggest marking your complexTypes with editor reuse attribute set to false - in this case, whenever selection changes to a different instance, property grid would still refresh your designers.
If you don't know what it does, why do you need to use it? Do you have any code that is using it currently that you could post as an example?
It sounds like it allows you to define that a property editor for your property can be reused without restarting. I am not particularly sure why this would be useful.