diff --git a/Bson/ObjectModel/BsonValue.cs b/Bson/ObjectModel/BsonValue.cs index 2dc352e478..11bd22ce5a 100644 --- a/Bson/ObjectModel/BsonValue.cs +++ b/Bson/ObjectModel/BsonValue.cs @@ -1543,7 +1543,7 @@ namespace MongoDB.Bson case BsonType.Double: return Convert.ChangeType(this.AsDouble, conversionType, provider); case BsonType.Int32: return Convert.ChangeType(this.AsInt32, conversionType, provider); case BsonType.Int64: return Convert.ChangeType(this.AsInt64, conversionType, provider); - case BsonType.ObjectId: return Convert.ChangeType(this, conversionType, provider); + case BsonType.ObjectId: return Convert.ChangeType(this.AsObjectId, conversionType, provider); case BsonType.String: return Convert.ChangeType(this.AsString, conversionType, provider); default: throw new InvalidCastException(); } diff --git a/Bson/ObjectModel/ObjectId.cs b/Bson/ObjectModel/ObjectId.cs index c0277a2df4..fe87d7cbd5 100644 --- a/Bson/ObjectModel/ObjectId.cs +++ b/Bson/ObjectModel/ObjectId.cs @@ -29,7 +29,7 @@ namespace MongoDB.Bson /// Represents an ObjectId (see also BsonObjectId). /// [Serializable] - public struct ObjectId : IComparable, IEquatable + public struct ObjectId : IComparable, IEquatable, IConvertible { // private static fields private static ObjectId __emptyInstance = default(ObjectId); @@ -464,5 +464,107 @@ namespace MongoDB.Bson { return BsonUtils.ToHexString(Pack(_timestamp, _machine, _pid, _increment)); } + + // explicit IConvertible implementation + TypeCode IConvertible.GetTypeCode() + { + return TypeCode.Object; + } + + bool IConvertible.ToBoolean(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + byte IConvertible.ToByte(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + char IConvertible.ToChar(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + DateTime IConvertible.ToDateTime(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + decimal IConvertible.ToDecimal(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + double IConvertible.ToDouble(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + short IConvertible.ToInt16(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + int IConvertible.ToInt32(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + long IConvertible.ToInt64(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + sbyte IConvertible.ToSByte(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + float IConvertible.ToSingle(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + string IConvertible.ToString(IFormatProvider provider) + { + return ToString(); + } + + object IConvertible.ToType(Type conversionType, IFormatProvider provider) + { + switch (Type.GetTypeCode(conversionType)) + { + case TypeCode.String: + return ((IConvertible)this).ToString(provider); + case TypeCode.Object: + if (conversionType == typeof(BsonObjectId)) + { + return new BsonObjectId(this); + } + if (conversionType == typeof(BsonString)) + { + return new BsonString(((IConvertible)this).ToString(provider)); + } + break; + } + + throw new InvalidCastException(); + } + + ushort IConvertible.ToUInt16(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + uint IConvertible.ToUInt32(IFormatProvider provider) + { + throw new InvalidCastException(); + } + + ulong IConvertible.ToUInt64(IFormatProvider provider) + { + throw new InvalidCastException(); + } } } diff --git a/BsonUnitTests/BsonUnitTests.csproj b/BsonUnitTests/BsonUnitTests.csproj index 973ebd2e9c..fad6815c8c 100644 --- a/BsonUnitTests/BsonUnitTests.csproj +++ b/BsonUnitTests/BsonUnitTests.csproj @@ -115,6 +115,7 @@ + diff --git a/BsonUnitTests/Jira/CSharp595Tests.cs b/BsonUnitTests/Jira/CSharp595Tests.cs new file mode 100644 index 0000000000..6c869739c1 --- /dev/null +++ b/BsonUnitTests/Jira/CSharp595Tests.cs @@ -0,0 +1,56 @@ +/* Copyright 2010-2012 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.Linq; +using System.Text; +using NUnit.Framework; + +using MongoDB.Bson; +using MongoDB.Bson.Serialization; + +namespace MongoDB.BsonUnitTests.Jira.CSharp595 +{ + [TestFixture] + public class CSharp595Tests + { + [Test] + public void TestDoesNotThrowStackOverflowExceptionWhenConvertingToSelfType() + { + BsonObjectId id1 = BsonObjectId.GenerateNewId(); + BsonObjectId id2 = null; + Assert.DoesNotThrow(() => + { + id2 = (BsonObjectId)((IConvertible)id1).ToType(typeof(BsonObjectId), null); + }); + + Assert.AreEqual(id1, id2); + } + + [Test] + public void TestDoesNotThrowStackOverflowExceptionWhenConvertingToBsonString() + { + BsonObjectId id1 = BsonObjectId.GenerateNewId(); + BsonString id2 = null; + Assert.DoesNotThrow(() => + { + id2 = (BsonString)((IConvertible)id1).ToType(typeof(BsonString), null); + }); + + Assert.AreEqual(id1.ToString(), id2.AsString); + } + } +} \ No newline at end of file