| Thomas 的个人资料Blogs日志列表 | 帮助 |
|
11月18日 The Listsearcher classWhile developing the new DOCexplorer, I created a class that allows to find objects in any Ilist class, by specifiying criterias that match for the object and it's properties. The Listsearcher class uses reflection to determine the public properties of the object within the list, and thus can perform a search for each property value. The search can be simple or complex by specifying an expression string with various kinds of comparisons and boolesic arithmetic, including nested brackets. For instance:
Are valid expressions. If no property name is specified, the comparer uses the object.ToString() result to compare, otherwhise the specified property. It's even not necessary to write the complete name of the property. Eq. if there is a property with the name "DayOfBirth", you can simply specify it by using the first letters, ignoring the charcase. So "day:1973" is a valid expression. With the LocaleProvider class (which has also been developed by myself to enable multilinguale applications as easy as possible) it's also possible, to specify more than one name for a property, thus the "DayOfBirth" property may be also accessed as "born", which is simpler to write and remember.
To optimize the performance while searching, the Listsearcher compiles an "in memory" class depending on the expression so the search is performed with full speed, as if it was written for this special purpose, as it IS compiled for this special purpose! Of course, the need to parse the expression and to compile it, before using it slows down a little bit, but that is not recognizable. The Listsearcher together with the developed UI input panel makes it easy to perform complex searches for any kinds of lists without the need to implement any search algorithm for the list. 11月17日 Threads and InvokesUsing threads is a very efficient way for modern programs to improve it's performance. So no serious developer today would write an application that would not benefit from threads. .NET makes the usage of threads very easy. The simplest way is to create a Thread class and give it a delegate that runs in the thread. You can also use the ThreadListPool and it's QueueUserWorkItem method to start a thread. The differene between the Thread class and the ThreadListPool is, as you may have already assumed, that the Thread starts instantly, while the ThreadListPool offers only a bunch of available Threads. So if you Queue a new Thread while all available threads are still running, the application has to wait until a thread becomes available. The ThreadListPool is very neat as it reduces the amount of simultaneously running threads, as to many threads would slow the system. But this is not always wanted, so it depends on the needs of the thread what kind you'll use. As you know, changing properties of visual controls like a Button or a TextBox is not allowed to be done by another thread but the creator of the class, which is used to be the main processes. But often you exactly write a thread that does something in the background and needs to inform the user interface about it's state eq. by refreshing a StatusBar. In pre .NET you where used to handle this by sending messages to the owner thread that finally actualizes the control. In .NET you have the Invoke method for every control. Invoke does simply nothing else but performing the specified delegate by the thread that owns the control rather than by the thread that performs the Invoke method. But this could cause some annoying extra code for creating the delegate and it's method in the way: You surely do recognize the overhead and it actually looks ugly. Forunately this can be simplified with the following technique, introducing the MethodInvoker class and anonymous delegates:
private void MyThread2()
The Secret of the BindingList.NET 2.0 knows many variations to collect data. The most familiar way is to use a List class, or what is more efficient a generic List class. With .NET you can also easily assign any kind of ICollections, which is an ancestor of IList to many visual controls like the ListView class or the DataGridView without the need t o write code to add each item to the control or to show the data. In most cases, reflections does this for you. But if you assign a List class to a control, the control is not aware of changes to the list, so what you need to do is to actualize each control that is bound to a List when the list got modified. Now this is the point when the BindingList class becomes interesting: To speed up the performance, the generic BindingList supports the functionality to temporarily disable to broadcast OnListChangedEvent when the list gets modified. This makes sense when you start to make wide ranges of modification to the list. Whilst doing this, every single change would fire a ListChangedEvent and every control bound to the list what actualize it's state, which could become time consuming. But If you temporarily disable the event by setting the RaiseListChangedEvent to false, any modification on the list is done WITHOUT raising a ListChangedEvent. But you mustn't forget to execute the ResetBindings method of the BindingList after you set RaiseListChangedEvent to true again, otherwhise the bounded controls would not be actualized.
Using BindingLists for visual controls is the most frequently usage of it, but you can also use it to inform other none visual classes that depend on the list that a change was made to react on the kind of change. For instance, I'm doing this for the XDTEngine of DOCexplorer, between IXdtFilter and IXdtParser.
One disadvantage of the BindingList generic class is, that unlike the generic List class, it does not offer support for sorting. But that's easily to solve. As the BindingList supports methods to get an List copy of all or some elements within the BindingList, you just need to create a temporarily copy of the BindingList, sort the List copy and than finally copy the List back to the BindingList. To easy this procedure, I wrote a special SortableBindingList class that offers the missing sorting support by doing this functionality as described.
|
|
|