Adapting a model to make binding simpler
I have a domain model composed by Clients, each client has a series of associated Typology objects and each Typology object has a certain number of associated Target. Now I need to bind this model to a series of three combo in WPF, but I have this little problem
The model is not directly accessible, I have already a service that has functions like GetAllCustomer, GetTyplogyForCustomer(Int32 customerId) and GetTargetForTyplogy(Int32 typologyId). Each method returns a list of the corresponding object, but they are DTO and not real object, so the Customer, Typology and Target returned from the service have no relation between them. Moreover I do not want to load everything when the application starts, because it will be extremely slow, I want to be able to load data as it needed, with lazy load. I created a couple of classes that I can use to lazily load entities
The LazyPartitionedList class is used to load collection of data partitioned by some value. I need such a base class for typology, I do not want to load all typologies in a single shot, I need only to load for currently selected customer, then when the current customer changed on the WPF interface I need to load (if it was not already loaded) from the service the list of typologies for the new customer. The LazyPartitionedList does this all for me. Then I create a browser class that link all toghether
|
|
The class analysisDefinitionBrowser have a lazycollection of customers (it loads all customer in one shot) then It has a LazyPartitionedCollection of TypologyDto partitioned by Client object. In the constructor of this object I initialize everything
|
|
Customers gets immediately loaded (Reinit Method), the interesting thing is that the LazyPartitionedCollection for typology Id is initialized with a function that calls the service to load typologies for current customer, actually no typology gets loaded. Another interesting thing is that using the CollectionViewSource I’m able to retrieve the default view for the Customer list.
|
|
The property CurrentClient have a particular Setter part, it loads the partition of the current Client object, then it copy in an ObservableCollection<TypologyDto> called currentTypologies only the typologies that are associated to current customer. With this trick if I already loaded that partition data are in memory and the service gets called only the first time, and only when it is needed. With this code I’ve created a class that load data only when it is needed, and keep selection in sync with the current properties. The beautiful thing of this object is that I can test it with no problem
|
|
The TestTemplate is used to create and setup mock for services, my services classes are static wrapper that permits me to override the real instance of service used, so I can use a different mock for each call of the service. Then the test simply setup some expectation and exercise the AnalysisDefinitionBrowser with direct manipulation of the ICollectionView object, thus simulating the user that changes currently selected item in the interface.
This test access the cvCustomers internal ICollectionView object because the Test assembly is InternalVisibleTo the test that contains the sut. The XAML code is something like this (I’ve bound a controller as the root source of the page, the controller initialize an instance of AnalysisDefinitoinBrowser and expose it with a dependency property called AnalysisDefinition)
|
|
Now when I fired the application and look into the sql server profiler I can see that object gets transparently loaded while I’m browsing the objects with the two combo, each time I select a new customer I see query that load related typologies, when I select a customer that was already selected in the past data are already in memory.
alk.