在ASP.NET MVC中使用Bitwise标志

时间:2015-02-12 11:19:32

标签: c# asp.net-mvc

我有一个ASP.NET MVC应用程序。我的应用程序在视图中使用剃须刀。我的视图有一个复选框列表。呈现的HTML如下所示:

<ul>
  <li>
    <input type="checkbox" name="SelectedValues" value="1" id="1" />
    <label for="1">Option 1</label>
  </li>

  <li>
    <input type="checkbox" name="SelectedValues" value="2" id="2" />
    <label for="2">Option 2</label>
  </li>

  <li>
    <input type="checkbox" name="SelectedValues" value="3" id="3" />
    <label for="3">Option 3</label>
  </li>

  <li>
    <input type="checkbox" name="SelectedValues" value="4" id="4" />
    <label for="4">Option 4</label>
  </li>
</ul>

当用户点击&#34;保存&#34;时,这些值会以int[] SelectedValues的形式存储在我的模型中。

我的挑战是,我的数据库只有一个int类型的字段。我可以在SelectedValues上进行某种按位XOR并且安全吗?如果是这样,我将如何在C#中的SelectedValues上执行此操作?

谢谢!

4 个答案:

答案 0 :(得分:3)

是的,你问的是可能的,唯一的问题是因为你选择了执行或会导致冲突的价值观。

例如:1 | 2 == 3代码如何选择1,2或仅3

解决方案是将其转换为位。您可以使用<<表示法执行此操作。 <<会将值向左移位一些位。

  • 1<<0为您提供100000001作为8位二进制文​​件
  • 1<<1为您提供100000010作为8位二进制文​​件
  • 1<<2为您提供100000100作为8位二进制文​​件
  • 1<<3为您提供100001000作为8位二进制文​​件
  • 1<<4为您提供100010000作为8位二进制文​​件

正如您所看到的,每个项目都有一个唯一的字节数组,因此您可以将它们或它们组合在一起以提供组合结果

  • 1<<0 | 1<<2以8位二进制文​​件为您提供500000101

这完全可以解决。

  • (5 & 1<<2) != 0会告诉您是否设置了第2位。

要实现,您可以使用Linq转换数组。

从你的整数数组中获取一个整数:

var array = new[] {1,2,4};
var result = array.Aggregate(0, (x,y) => x | 1<<(y-1));

我从每个值中取出1,因此1的int值变为1

要反转此操作,您可以再次使用linq创建数组。

var value = 5;
var result = Enumerable.Range(1,8).Select(x => (value & 1<<(x-1)) !=0).ToArray();

这将返回一个bool数组,指示每个位的真或假。

只获取设定值列表:

var value = 5;
var result = Enumerable.Range(1,8).Where(x => (value & 1<<(x-1))!=0).Select(x => 1 << (x-1)).ToArray();

此功能适用于8个值,但会将其更改为适合。

请记住,您可以存储在一个整数中的最大位数,检查其16位整数的大小,其他为32位。 c#作为一种语言有32位整数,更长时间使用。

此外,您不应该使用最高位,因为有符号整数使用最高位进行签名。

答案 1 :(得分:1)

首先,你的值是错误的,你需要使用与被设置的位相关的标志,1248,{{ 1}} ...等

16

所以

1 == 0001
2 == 0010
4 == 0100
8 == 1000
etc.

然后你只需加上你的int

<ul>
  <li>
    <input type="checkbox" name="SelectedValues" value="1" id="1" />
    <label for="1">Option 1</label>
  </li>

  <li>
    <input type="checkbox" name="SelectedValues" value="2" id="2" />
    <label for="2">Option 2</label>
  </li>

  <li>
    <input type="checkbox" name="SelectedValues" value="4" id="3" />
    <label for="3">Option 3</label>
  </li>

  <li>
    <input type="checkbox" name="SelectedValues" value="8" id="4" />
    <label for="4">Option 4</label>
  </li>
</ul>

或使用linq:

int bitFlag = 0;
if (Model.SelectedValues !=null)
{
   foreach(int value in Model.SelectedValues)
        bitFlag += value;
}

因此,int bitFlag = 0; if (Model.SelectedValues !=null) bitFlag = Model.SelectedValues.Sum(s => s); 1被检查为40101为整数

答案 2 :(得分:1)

对于我的罪过,我做过这个练习。我已将数据存储在C#Flag Enum中(这是一种以按位方式存储枚举的方式)并显示在UI中。

在您的示例中,枚举类似于

[Flags]
public enum SelectedValues
{
    [Display("Option 1")]
    Option1= 1,

    [Display("Option 2")]
    Option2= 2,

    [Display("Option 3")]
    Option3= 4,

    [Display("Option 4")]
    Option4= 8
}

在您的示例中,您的视图模型必须具有SelectedValues类型的成员。

然后我使用显示模板设置一组复选框。我是通过为Flag Enums

创建HTML帮助程序来实现的
public static class FlagEnumHelpers
{
    public static IHtmlString CheckBoxForFlagEnum<T>(this HtmlHelper<T> html, Enum item) 
    {

        TemplateInfo templateInfo = html.ViewData.TemplateInfo;
        string id = templateInfo.GetFullHtmlFieldId(item.ToString());
        string name = templateInfo.GetFullHtmlFieldId(string.Empty);

        var checkbox = new TagBuilder("input");
        checkbox.Attributes["id"] = id;
        checkbox.Attributes["name"] = name;
        checkbox.Attributes["type"] = "checkbox";
        checkbox.Attributes["value"] = item.ToString();

        var model = html.ViewData.Model as Enum;

        if (model != null && model.HasFlag(item))
        {
            checkbox.Attributes["checked"] = "checked";
        }

        return MvcHtmlString.Create(checkbox.ToString());
    }
}

然后创建了一个编辑模板(在Views / Shared / EditorTemplates中),在你的情况下称为SelectedValues.cshtml,看起来像

  @model Your.Namespace.SelectedValues?
  <ul>
     <li>
     @Html.CheckBoxForFlagEnum(SelectedValues.Option1)
     </li>
     <li>
     @Html.CheckBoxForFlagEnum(SelectedValues.Option2)
     </li>
     <li>
     @Html.CheckBoxForFlagEnum(SelectedValues.Option3)
     </li>
     <li>
     @Html.CheckBoxForFlagEnum(SelectedValues.Option4)
     </li>
  </ul>

老实说虽然我对它不满意。我认为MVC和Enums /按位操作不能很好地相互配合。

答案 3 :(得分:-1)

另存为Option 1 | Option 2 | Option 3 | Option 4 但为此目的,您的值必须为1 2 4 8 16 32 ...,依此类推