MongoDB和派生类

时间:2018-10-22 20:52:09

标签: c# mongodb

我无法在MongoDB中保存特定的类。

我的抽象类如下:

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);
}

派生类:

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;
}
}

当我尝试保存具有SeatState作为属性的类时,mongo抛出此错误:

System.ArgumentOutOfRangeException:memberInfo参数必须适用于SeatState类,但适用于Enumeration类。

我也尝试了BsonClassMap.RegisterClassMap<Enumeration>()(有和没有IsRootClassBsonClassMap.RegisterClassMap<SeatState>() 但没有成功。看来问题出在静态属性上,但我需要它们。

任何对我做错事的澄清都将受到赞赏。

1 个答案:

答案 0 :(得分:0)

对于其他可能遇到相同问题的人,解决方案如下:

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));
});