Simplified Criteria Syntax
The new version of XPO (in the DXperience 6.2 release) includes a feature we have kept secret so far. It has to do with the way you write criteria in code.
What we had before
Let me remind you of the common ways to do this today.
Approach 1: Create criteria in code as objects.
CriteriaOperator op = new BinaryOperator("Name", "Winny");
Approach 2: Use the static method CriteriaOperator.Parse().
CriteriaOperator op = CriteriaOperator.Parse("Name = 'Winny'");
Approach 1 has the main drawback that it's a lot of code to write. It can also be pretty difficult to come up with the complete hierarchies of operators that are frequently needed for complex expressions. Approach 2 offers a solution to these problems by using a less verbose but powerful query language. The drawback here is that there's no checking at all for complex expressions basically stored in string variables in the code you write. If you are creating operator classes in code, you can of course make mistakes writing the names of fields, or comparing things that can’t really be compared – both approaches are far from being type-safe. But in case 2 there are suddenly a lot more mistakes you can make, because the whole string containing the query expression can't be checked and thus can easily bring up runtime errors.
The new approach
The new approach is not meant to remove the need for either or both of the above. Instead it is an extension that can be used in conjunction with, or as an alternative to, both existing approaches. Basically, using the new syntax, you would now write the above criterion like this:
CriteriaOperator op = MyClass.Fields.Name == "Winny";
Let's take a look at how this works. Internally, we use some clever operator overloading to allow for the == operator to be used in this scenario. The expression on the left hand side has to be of type OperandProperty for this to work, so you could use the following piece of code with the same outcome:
OperandProperty prop = new OperandProperty("Name"); CriteriaOperator op = prop == "Winny";
Very nice. Now, where does that MyClass.Fields thingy come from in the first example? Very easy: we assume that there's a nested class called Fields inside the class MyClass, which would be your persistent class in the example.
The Fields class recommendation
Obviously we can't force our XPO users to follow our ideas in this regard, so we call this the "Fields class recommendation". This recommendation says that your persistent class MyClass should look like this:
public class MyClass: XPObject { public MyClass(Session session): base(session) { }
private string name; public string Name { get { return name; } set { if (name != value) { string oldValue = name; name = value; OnChanged("Name", oldValue, name); } } }
public class Fields { private Fields() { } public static OperandProperty Name { get { return new OperandProperty("Name"); } } } }
Now I'm sure you're thinking something like "This is all very nice, but wouldn't it be even nicer if somebody made a suggestion that doesn't involve a huge amount of additional work for me?". Or maybe you weren't using nice words like this in your mind.
Well, wait for it: we give you the tool that inserts the Fields class automatically for you in the correct format!
The Fields class DXCore plug-in
The DXperience 6.2 distribution contains DXCore, our free Visual Studio extensibility layer, which forms the basis of CodeRush and Refactor!. Based on DXCore, we have implemented a plug-in to do the grunt work of the Fields class recommendation. This plug-in is also part of the DXperience package, but it is disabled by default.
We made the decision to deliver the plug-in in a disabled state because as soon as it is active, it will start making changes to persistent classes you are editing in your code. Let me repeat this: As soon as it is activated, the plug-in will make changes to persistent classes you are editing in your code!
To activate the plug-in, there's an option you must set in the DXCore options dialog. In Visual Studio, use the DevExpress | Options... menu entry. In the options dialog select Editor / XPO / General from the tree list on the left hand side and check the option XPO Field Synchronization enabled.

Once you have activated the plug-in as described above, you'll notice its presence as soon as you make changes to an existing persistent class, or create a new one. When you are adding persistent properties or fields to the class, the plug-in immediately adds the corresponding properties to the nested Fields class (or creates the Fields class if it's not yet there). By clicking on the small symbol next to a persistent property, you can exclude that property from the Fields class.
We have a number of plans for further extensions to this plug-in, but please let us know of any additional ideas you may have. Of course we also want to hear about problems of any kind.
More operators
Of course the new system doesn't only allow to use the == operator, but a number of others as well. The list of supported operators is ==, !=, >, <, >=, <=, +, -, *, /, %, !, & and |. For technical reasons, we suggest you use the single & and | operators instead of && or ||.
Of course you can use the new-style expressions in all places where you could otherwise pass in instances of CriteriaOperators. For example, directly in the constructor call for an XPCollection<T>:
XPCollection<Person> coll = new XPCollection<Person>(session, Person.Fields.Name == "Winny" & Person.Fields.Age > 30);
Have fun!
To learn more about XPO, please write to us at: info@devexpress.com.
To order your copy, visit our online order page.
|