[CSHARP-401] Implementing custom IdMemberConvention and ElementNameConvention Created: 21/Feb/12 Updated: 02/Apr/15 Resolved: 21/Feb/12 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | Feature Request |
| Affects Version/s: | 1.3.1 |
| Fix Version/s: | 1.4 |
| Type: | Improvement | Priority: | Major - P3 |
| Reporter: | Robert Poskevich | Assignee: | Robert Stam |
| Resolution: | Done | Votes: | 0 |
| Labels: | driver | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Mono 2.10.8, OS X |
||
| Description |
|
When creating multiple instances of MongoCollection<T>, each representing separate database collections, it is possible to encounter naming collisions between classes in calling into custom IdMemberConvention and ElementNameConvention classes. The following code better illustrates my point. class A } class AB : A { ObjectId ABId { get; set; } } public class IdMemberConvention : IIdMemberConvention public IdMemberConvention () { this._idMembers = new Dictionary<Type,string> (); }public void SetIdMember (Type type, string name) { this._idMembers[type] = name; } public string FindIdMember (Type type) catch { return null; } } For both classes A and AB I would call IdMemberConvention's SetIdMember method as follows, respectively; SetIdMember(typeof(A), "Id"); However, this is problematic for me, as BsonClassMap calls "FindIdMember" in a recursive manner, such that the base-most class is first passed into "FindIdMember" and on up the type chain until a non-null value is returned. And so the "FindIdMember" method, in the case of type A, is called twice; first for base type System.Object and secondly for type A. Furthermore, type AB results in three calls to "FindIdMember" (assuming that the id property is not found in a base class) which are, respectively, types System.Object, A and AB. The problem arises in fetching the id member for type AB. Because AB extends class A, and I have set the id member for type A (i.e. SetIdMember(typeof(A), "Id")) as well as for type AB, "FindIdMember" would return "Id" instead of the expected "ABId". A solution to this problem, and one I'll quickly implement for my purposes, would be to send the collection type, AB in this example, to the "FindIdMember" method, so that I could distinguish a call to "FindIdMember" between types A and AB. What do you think of this solution? Is there a cleaner way to achieve this? Is my implementation pattern here all wrong? Thanks. I hope this is helpful. |
| Comments |
| Comment by Robert Stam [ 21/Feb/12 ] |
|
I think it's OK for me to close this JIRA now. If you still have a pending issue please add a comment and reopen it. |
| Comment by Robert Poskevich [ 21/Feb/12 ] |
|
Ok, that's a great point. I've added an Exception to my IdMemberConvention that should prevent me from using it incorrectly. Thanks again. |
| Comment by Robert Stam [ 21/Feb/12 ] |
|
Here's a sample program testing your classes and convention: I set a breakpoint on FindIdMember in the custom convention and it is only called once for type A. Note that I only call SetIdMember on the convention for type A because only the root class can have an _id property. Note that the ABId property is treated like a regular data field and is not associated with the _id. |
| Comment by Robert Stam [ 21/Feb/12 ] |
|
In an inheritance hierarchy the _id element (whatever it is called in your POCO) must be a property of the root class. It looks like you want your AB class to have a different _id than the A class. If that's the case, then AB shouldn't derive from A. |