[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
{
ObjectId Id

{ get; set; }
}

class AB : A
{
ObjectId ABId { get; set; }

}

public class IdMemberConvention : IIdMemberConvention
{
private Dictionary<Type,string> _idMembers;

public IdMemberConvention ()

{ this._idMembers = new Dictionary<Type,string> (); }

public void SetIdMember (Type type, string name)

{ this._idMembers[type] = name; }

public string FindIdMember (Type type)
{
try

{ return this._idMembers[type]; }

catch

{ return null; }

}
}

For both classes A and AB I would call IdMemberConvention's SetIdMember method as follows, respectively;

SetIdMember(typeof(A), "Id");
SetIdMember(typeof(AB), "ABId");

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:

http://www.pastie.org/3428513

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.

Generated at Wed Feb 07 21:36:43 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.