【发布时间】:2019-08-08 15:24:30
【问题描述】:
我有一个数据库模型,它使用.HasFlag 将设置存储为 32 位整数上的位。前端使用 AngularJs (1),可悲的是 does not allow bit-wise operations in expressions。因此,我创建了一个扩展方法来从 Enum 转换为每个标志的字典,以及它是否打开:
public static IDictionary<TEnum, bool> GetAllFlags<TEnum>(this TEnum obj) where TEnum: Enum
{
return Enum.GetValues(typeof(TEnum))
.Cast<TEnum>()
.ToDictionary(flag => flag, flag => obj.HasFlag(flag));
}
我还创建了一个扩展方法来设置值,但它依赖于其他扩展方法并且它不会被调用(如下所述),所以为了简洁起见,我将它们排除在外。
这是一个使用枚举的示例(注意它的类型默认为 int 并且选项很少,但它确实为 0 定义了一个,这很奇怪)
public enum Settings
{
None = 0,
Setting1 = 1,
Setting2 = 2,
Setting3 = 4,
}
所有这些都暴露为像这样的对象上的属性
// SettingsFlags comes from another partial and is a Settings enum persisted to the database as an `INT`
public parital class Options
{
IDictionary<Settings, bool> Flags {
get { return SettingsFlags.GetAllFlags(); }
set { SettingsFlags.SetAllFlags(value); } // this never gets called
}
}
当为客户端序列化为JSON 时,这非常有用。但是,当在请求中收到它时,它会引发以下异常:
System.InvalidCastException: Specified cast is not valid.
at System.Web.Mvc.DefaultModelBinder.CollectionHelpers.ReplaceDictionaryImpl[TKey,TValue](IDictionary`2 dictionary, IEnumerable`1 newContents)
当进入调试器时,get 块被调用并返回预期的字典。之后,在调试器中无需额外步骤即可引发错误。
这是端点外观的示例(它不符合 REST):
public JsonResult UpdateSingleItem(Options options, ...)
{ // breakpoint here is never called.
....
}`
使用ReSharper 和DotPeak 来检查代码会为我提供以下引发错误的方法:
// System.Web.Mvc.DefaultModelBuilder.CollectionHelpers
private static void ReplaceDictionaryImpl<TKey, TValue>(
IDictionary<TKey, TValue> dictionary,
IEnumerable<KeyValuePair<object, object>> newContents)
{
dictionary.Clear();
foreach (KeyValuePair<object, object> newContent in newContents)
{
TKey key = (TKey) newContent.Key;
TValue obj = newContent.Value is TValue ? (TValue) newContent.Value : default (TValue);
dictionary[key] = obj;
}
}
【问题讨论】:
标签: c# asp.net .net asp.net-mvc enums