Reputation: 9271
I am having trouble saving a particular class with MongoDB.
My abstract class is as follow:
public abstract class Enumeration : IComparable
{
public string Name { get; }
public int Id { get; }
protected Enumeration(int id, string name)
{
Id = id;
Name = name;
}
public override string ToString() => Name;
public static IEnumerable<T> GetAll<T>() where T : Enumeration
{
var fields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
return fields.Select(f => f.GetValue(null)).Cast<T>();
}
public override bool Equals(object obj)
{
var otherValue = obj as Enumeration;
if (otherValue == null)
return false;
var typeMatches = GetType().Equals(obj.GetType());
var valueMatches = Id.Equals(otherValue.Id);
return typeMatches && valueMatches;
}
public override int GetHashCode() => Id.GetHashCode();
public static int AbsoluteDifference(Enumeration firstValue, Enumeration secondValue)
{
var absoluteDifference = Math.Abs(firstValue.Id - secondValue.Id);
return absoluteDifference;
}
public static T FromValue<T>(int value) where T : Enumeration
{
var matchingItem = Parse<T, int>(value, "value", item => item.Id == value);
return matchingItem;
}
public static T FromDisplayName<T>(string displayName) where T : Enumeration
{
var matchingItem = Parse<T, string>(displayName, "display name", item => item.Name == displayName);
return matchingItem;
}
private static T Parse<T, K>(K value, string description, Func<T, bool> predicate) where T : Enumeration
{
var matchingItem = GetAll<T>().FirstOrDefault(predicate);
if (matchingItem == null)
throw new InvalidOperationException($"'{value}' is not a valid {description} in {typeof(T)}");
return matchingItem;
}
public int CompareTo(object other) => Id.CompareTo(((Enumeration)other).Id);
}
The derived class:
public class SeatState : Enumeration
{
public static SeatState Free = new SeatState(1, nameof(Free).ToLowerInvariant());
public static SeatState Booked = new SeatState(2, nameof(Booked).ToLowerInvariant());
public static SeatState Reserved = new SeatState(3, nameof(Reserved).ToLowerInvariant());
public static IEnumerable<SeatState> List() => new[] { Free, Booked, Reserved };
public SeatState(int id, string name)
: base(id, name)
{
}
public static SeatState FromName(string name)
{
var state = List().SingleOrDefault(s => string.Equals(s.Name, name, StringComparison.CurrentCultureIgnoreCase));
if (state == null)
throw new Exception($"Possible values for SeatState: {string.Join(",", List().Select(s => s.Name))}");
return state;
}
public static SeatState From(int id)
{
var state = List().SingleOrDefault(s => s.Id == id);
if (state == null)
throw new Exception($"Possible values for SeatState: {string.Join(",", List().Select(s => s.Name))}");
return state;
}
}
When I try to save a class that have SeatState
as a property, mongo throw this error:
System.ArgumentOutOfRangeException: The memberInfo argument must be for class SeatState, but was for class Enumeration.
I tried also with BsonClassMap.RegisterClassMap<Enumeration>()
(with and without IsRootClass
) and BsonClassMap.RegisterClassMap<SeatState>()
but without success. It seems that the problem lie in the static properties, but I need them.
Any clarification in what I am doing wrong is greatly appreciated.
Upvotes: 0
Views: 1580
Reputation: 9271
For others who may have the same problem, the solution is as follow:
BsonClassMap.RegisterClassMap<Enumeration>(cm =>
{
cm.SetIsRootClass(true);
cm.MapMember(m => m.Id);
cm.MapMember(m => m.Name);
});
BsonClassMap.RegisterClassMap<SeatState>(cm =>
{
cm.MapCreator(c => new SeatState(c.Id, c.Name));
});
Upvotes: 3