次のようなユーザー権限の列挙型があります。
[Flags]
public enum UserPrivileges : byte
{
None = 0, // 0000 0000
View = 1 << 0, // 0000 0001
Import = 1 << 1, // 0000 0010
Export = 1 << 2, // 0000 0100
Supervisor = View | Import | Export | 1 << 3, // 0000 1111
Admin = Supervisor | 1 << 4 // 0001 1111
}
これらの値は、値コンバーターを使用して GUI の CheckBoxes にバインドされます。(さまざまな特権 [eg EmployeePrivileges] もあるため、これをできるだけ一般的にしたかった)
public class ByteFlagsEnumValueConverter : IValueConverter
{
private byte _targetValue;
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
var mask = (byte)parameter;
_targetValue = (byte)value;
return ((mask | _targetValue) == _targetValue);
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
var mask = (byte)parameter;
if ((bool)value)
{
_targetValue |= mask;
}
else
{
// Get next superflag for mask (e.g. 0110 -> 1111)
var b = mask;
b--;
b |= (byte)(b >> 1);
b |= (byte)(b >> 2);
b |= (byte)(b >> 4);
b |= (byte)(b >> 8);
// if you remove a superflag (e.g. 1111) also remove
// everything higher than this flag
if (mask == b || mask == 1)
_targetValue &= (byte)(mask >> 1);
else
// ????????
}
return Enum.Parse(targetType, _targetValue.ToString());
}
}
これは、GUI でユーザーに特権を表示および追加するのに非常にうまく機能します。また、スーパーバイザーなどのスーパーフラグを削除する場合にも機能します (スーパーバイザーのすべてのフラグ>=
が削除され、他のフラグは変更されません)。
問題は、たとえば、インポートのチェックを外すときです。すべてのスーパーフラグ (スーパーバイザー、管理者) を削除したいが、他のフラグ (ビュー、エクスポート) は保持したいです。
0001 1111 // Admin
0000 0010 // Import
---------
0000 0101 // View | Export
しかし、私はこれを達成するための良いアイデアを思いつきませんでした。これに対する良い解決策を持っている人はいますか?