//interface for objects with Id
interface IPersistentObject {
long Id { get; }
}
//reference container
public class Ref<T> : IPersistentObject, IEquatable<long> where T : IPersistentObject, new(){ public long Id { get; set; }
private T _Object;
public T Get() { return _Object; }
public void Set(T value) { _Object = value; Id = value == null ? 0L : value.Id; }
//... Equals() and IEquatable implemetation here}
//serializer implementation
public class RefSerializer<T> : SerializerBase<Ref<T>> where T : IPersistentObject, new(){ public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Ref<T> value) { long v = value; context.Writer.WriteInt64(v); } public override Ref<T> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var id = context.Reader.ReadInt64(); return new Ref<T> {Id = id}; }}
//both Sample and SampleWithReference types are mapped to separate collections
public class Sample : IPersistentObject{ public long Id { get; set; }}
public class SampleWithReference : IPersistentObject{
public long Id { get; set; }
public Ref<Sample> Parent { get; set; }}
//somewhere in the code
var r = new SampleWithReference();
r.Parent.Set(new Sample());
//and save it all to DB
{
"_id": 94329387,
"Parent": 574832483
}
//the following can't be compiled
from r in DB.Query<SampleWithReference>()join s in DB.Query<Sample>() on r.Parent equals s.Idselect s;
//this works but filter points to Parent.Id which doesn't exist
//in document because Parent object is being serialized to plain int64
from r in DB.Query<SampleWithReference>()join s in DB.Query<Sample>() on r.Parent.Id equals s.Idselect s;
public class Ref<T> : RefId where T : IPersistentObejct, new()
public class RefId : IEquatable<long>, IEqualityComparer<long>{ protected long Id; public override bool Equals(object obj) { if (obj == null) return false; return Id == (long)obj; }
public override int GetHashCode() { return Id.GetHashCode(); }
public override string ToString() { return Id.ToString(); }
public bool Equals(long other) { return Id.Equals(other); }
public bool Equals(long x, long y) { return x.Equals(y); }
public int GetHashCode(long obj) { return Id.GetHashCode(); }
public static implicit operator RefId(long id) { return new RefId() { Id = id }; }
public static implicit operator long(RefId idref) { return idref.Id; }}
public RefId Id { get; internal set; }
We'll have to find some kind of extension point to expose that you can use.