From c35dcfeabc7ce0c85ac8f299591f7f36d4c06db3 Mon Sep 17 00:00:00 2001 From: rstam Date: Fri, 22 Oct 2010 17:19:25 -0400 Subject: [PATCH] Fixed CSHARP-81. The IdPropertyMap for a class map should come from the highest class possible in the inheritance hierarchy. --- Bson/DefaultSerializer/BsonClassMap.cs | 52 +++++++++++++---------- BsonUnitTests/BsonUnitTests.csproj | 1 + BsonUnitTests/Jira/CSharp81Tests.cs | 59 ++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 23 deletions(-) create mode 100644 BsonUnitTests/Jira/CSharp81Tests.cs diff --git a/Bson/DefaultSerializer/BsonClassMap.cs b/Bson/DefaultSerializer/BsonClassMap.cs index d4414623af..c8593e9735 100644 --- a/Bson/DefaultSerializer/BsonClassMap.cs +++ b/Bson/DefaultSerializer/BsonClassMap.cs @@ -40,6 +40,7 @@ namespace MongoDB.Bson.DefaultSerializer { protected string discriminator; protected bool discriminatorIsRequired; protected bool isAnonymous; + protected bool idPropertyMapLoaded; // lazy load idPropertyMap protected BsonPropertyMap idPropertyMap; protected List propertyMaps = new List(); protected bool ignoreExtraElements = true; @@ -82,16 +83,8 @@ namespace MongoDB.Bson.DefaultSerializer { public BsonPropertyMap IdPropertyMap { get { - if (idPropertyMap != null) { - return idPropertyMap; - } else { - var baseClassMap = BaseClassMap; // call property for lazy loading - if (baseClassMap != null) { - return baseClassMap.IdPropertyMap; - } else { - return null; - } - } + if (!idPropertyMapLoaded) { LoadIdPropertyMap(); } + return idPropertyMap; } } @@ -377,19 +370,6 @@ namespace MongoDB.Bson.DefaultSerializer { propertyMaps = new List(ordered.Concat(propertyMaps.Where(pm => pm.Order == int.MaxValue))); } - // TODO: improve Id detection algorithm (doesn't have to be perfect since BsonIdAttribute can always pinpoint the Id property) - // simple algorithm: first property found that ends in either "Id" or "id" or is of type ObjectId or Guid - if (idPropertyMap == null) { - idPropertyMap = propertyMaps - .Where(pm => - pm.PropertyName.EndsWith("Id") || - pm.PropertyName.EndsWith("id") || - pm.PropertyType == typeof(ObjectId) || - pm.PropertyType == typeof(Guid) - ) - .FirstOrDefault(); - } - RegisterDiscriminator(classType, discriminator); } @@ -452,6 +432,32 @@ namespace MongoDB.Bson.DefaultSerializer { } baseClassMapLoaded = true; } + + private void LoadIdPropertyMap() { + if (idPropertyMap == null) { + // the IdPropertyMap should be provided by the highest class possible in the inheritance hierarchy + var baseClassMap = BaseClassMap; // call BaseClassMap property for lazy loading + if (baseClassMap != null) { + idPropertyMap = baseClassMap.IdPropertyMap; + } + + // if no base class provided an idPropertyMap maybe we have one? + if (idPropertyMap == null) { + // TODO: improve Id detection algorithm (doesn't have to be perfect since BsonIdAttribute can always pinpoint the Id property) + // simple algorithm: first property found that ends in either "Id" or "id" or is of type ObjectId or Guid + idPropertyMap = propertyMaps + .Where(pm => + pm.PropertyName.EndsWith("Id") || + pm.PropertyName.EndsWith("id") || + pm.PropertyType == typeof(ObjectId) || + pm.PropertyType == typeof(Guid) + ) + .FirstOrDefault(); + } + } + + idPropertyMapLoaded = true; + } #endregion } diff --git a/BsonUnitTests/BsonUnitTests.csproj b/BsonUnitTests/BsonUnitTests.csproj index ce8adffe69..3ffcecd81d 100644 --- a/BsonUnitTests/BsonUnitTests.csproj +++ b/BsonUnitTests/BsonUnitTests.csproj @@ -80,6 +80,7 @@ + diff --git a/BsonUnitTests/Jira/CSharp81Tests.cs b/BsonUnitTests/Jira/CSharp81Tests.cs new file mode 100644 index 0000000000..29f681c542 --- /dev/null +++ b/BsonUnitTests/Jira/CSharp81Tests.cs @@ -0,0 +1,59 @@ +/* Copyright 2010 10gen Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Xml; +using NUnit.Framework; + +using MongoDB.Bson; +using MongoDB.Bson.IO; +using MongoDB.Bson.DefaultSerializer; +using MongoDB.Bson.Serialization; + +namespace MongoDB.BsonUnitTests.Jira { + [TestFixture] + public class CSharp81Tests { + private class BaseModel { + [BsonId] + public ObjectId Id { get; set; } + } + + private class User : BaseModel { + public ObjectId FriendId { get; set; } + } + + [Test] + public void TestIdProperty() { + var u = new User { Id = ObjectId.Empty, FriendId = ObjectId.Empty }; + + var classMap = BsonClassMap.LookupClassMap(typeof(User)); + var idPropertyMap = classMap.IdPropertyMap; + Assert.AreEqual("Id", idPropertyMap.PropertyName); + + var serializer = BsonSerializer.LookupSerializer(typeof(User)); + var idGenerator = BsonSerializer.LookupIdGenerator(typeof(ObjectId)); + serializer.GenerateDocumentId(u); + Assert.IsFalse(idGenerator.IsEmpty(u.Id)); + Assert.IsTrue(idGenerator.IsEmpty(u.FriendId)); + + var json = u.ToJson(); + } + } +}