Extend Enum with flag methods? - c#

I have found good examples on how to create extension methods to read out single values from bitwise enums. But now that C# 4 has added the HasFlag method they are really not needed.
What I think would be really helpful though is an extension to SET a single flag!
I have many situations where I need to set the flag values individually.
I want an extension method with this signature:
enumVariable.SetFlag(EnumType.SingleFlag, true);
OR possibly:
enumVariable.SetFlag<EnumType>(EnumType.SingleFlag, true);

Today I found a solution on http://hugoware.net/blog/enums-flags-and-csharp. Thanks Hugo! Excellent code that works fine. I adjusted it slightly and added it to my existing EnumExtender:
public static class EnumExtender
{
/// <summary>
/// Adds a flag value to enum.
/// Please note that enums are value types so you need to handle the RETURNED value from this method.
/// Example: myEnumVariable = myEnumVariable.AddFlag(CustomEnumType.Value1);
/// </summary>
public static T AddFlag<T>(this Enum type, T enumFlag)
{
try
{
return (T)(object)((int)(object)type|(int)(object)enumFlag);
}
catch(Exception ex)
{
throw new ArgumentException(string.Format("Could not append flag value {0} to enum {1}",enumFlag, typeof(T).Name), ex);
}
}
/// <summary>
/// Removes the flag value from enum.
/// Please note that enums are value types so you need to handle the RETURNED value from this method.
/// Example: myEnumVariable = myEnumVariable.RemoveFlag(CustomEnumType.Value1);
/// </summary>
public static T RemoveFlag<T>(this Enum type, T enumFlag)
{
try
{
return (T)(object)((int)(object)type & ~(int)(object)enumFlag);
}
catch (Exception ex)
{
throw new ArgumentException(string.Format("Could not remove flag value {0} from enum {1}", enumFlag, typeof(T).Name), ex);
}
}
/// <summary>
/// Sets flag state on enum.
/// Please note that enums are value types so you need to handle the RETURNED value from this method.
/// Example: myEnumVariable = myEnumVariable.SetFlag(CustomEnumType.Value1, true);
/// </summary>
public static T SetFlag<T>(this Enum type, T enumFlag, bool value)
{
return value ? type.AddFlag(enumFlag) : type.RemoveFlag(enumFlag);
}
/// <summary>
/// Checks if the flag value is identical to the provided enum.
/// </summary>
public static bool IsIdenticalFlag<T>(this Enum type, T enumFlag)
{
try
{
return (int)(object)type == (int)(object)enumFlag;
}
catch
{
return false;
}
}
/// <summary>
/// Convert provided enum type to list of values.
/// This is convenient when you need to iterate enum values.
/// </summary>
public static List<T> ToList<T>()
{
if (!typeof(T).IsEnum)
throw new ArgumentException();
var values = Enum.GetNames(typeof(T));
return values.Select(value => value.ToEnum<T>()).ToList();
}
/// <summary>
/// Present the enum values as a comma separated string.
/// </summary>
public static string GetValues<T>()
{
if (!typeof(T).IsEnum)
throw new ArgumentException();
var values = Enum.GetNames(typeof(T));
return string.Join(", ", values);
}
}

I've done something that works for me and very simple. Probably not efficient due to dynamic casting usage. But perhaps you could like it?
public static T SetFlag<T>(this Enum value, T flag, bool set)
{
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
// note: AsInt mean: math integer vs enum (not the c# int type)
dynamic valueAsInt = Convert.ChangeType(value, underlyingType);
dynamic flagAsInt = Convert.ChangeType(flag, underlyingType);
if (set)
{
valueAsInt |= flagAsInt;
}
else
{
valueAsInt &= ~flagAsInt;
}
return (T)valueAsInt;
}

I'm not sure what your question is here, but if you're asking if this is possible, I'd have to say that it isn't, not with this exact syntax.
Enums are value types, and as such, are passed by value. So a method, such as SetFlag, that receives an enum value will receive a COPY of it. Even if it sets a flag, that change would be confined to the method scope, not to the enum that it's called on.
You can pass it to a method with the ref modifier, like this: SetFlag(ref enumVariable, EnumType.SingleFlag) but this isn't supported as an extension method, as far as I know.
What you can do is either create a general enum helper class:
public static class EnumHelper
{
public void SetFlag<TEnum>(ref TEnum enumValue, TEnum flag)
{
enumValue = enumValue | flag;
}
}
or, alternately, create a SetFlag method that returns a new value rather than modifying the existing variable.
public static TEnum SetFlag<TEnum>(this TEnum enumValue, TEnum flag)
{
return enumValue | flag;
}

Maybe not as pretty as you'd hoped but you can do it quite simply :)
enumVariable |= EnumType.SingleFlag;

You maybe need to implement the method for each enum because you can't constraint a enum this way:
public static T SetFlag<T>(this T #this, T flag, Boolean state) where T : enum { ... }
Anyway operator overloads are not allowed in C# on generic types, so you can't use the generic type T without casting.
Solution
So your extension methods must look like this:
public static MyFlag SetFlag(this MyFlag #this, MyFlag flag, Boolean state)
{
return state ? (#this | flag) : (#this & ~flag);
}

Related

MongoDb c# driver enum mapping

I have Enum:
public enum SomeType
{
TypeA,
TypeB,
TypeC
}
but in MongoDB i would like this map to:
type_a type_b type_c
I'm using EnumRepresentationConvention(BsonType.String)
I tried:
public enum SomeType
{
[BsonElement("type_a")]
TypeA,
[BsonElement("type_b")]
TypeB,
[BsonElement("type_c")]
TypeC
}
but this doesn't work. Im getting exception:
Requested value 'type_a' was not found.
Is anyone know how can achieve such mapping in MongoDb C# driver?
UPDATE
So I wrote a new serializer that does what you need. I built it off some code I wrote as part of SharpExtensions. It certainly isn't optimized (or as simplified as it could be) but it works.
First I created a sample class Foo and reused your example Enum. I then leveraged the DescriptionAttribute to specify an alternate representation of the Enum that you completely control. Though this could be potentially simplified if you leverage something like Humanizer to consistently change the representation.
I then created a BsonSerializationProvider to let the driver know when it should use that serializer (much like my original answer). The meat is in EnumDescriptionSerializer which uses reflection to find the string representation of a particular value of SomeType. This is where I leverage the boilerplate code from SharpExtensions to move between the string and the actual Enum value. You'll notice the code will also work with EnumMemberAttribute as well as DescriptionAttribute. Please feel free to import the SharpExtensions library if you don't want to use the boilerplate code directly.
public class Foo
{
public ObjectId Id {get;set;}
public SomeType Enum {get;set;}
}
public enum SomeType
{
[Description("type_a")]
TypeA,
[Description("type_b")]
TypeB,
[Description("type_c")]
TypeC
}
public class EnumDescriptionSerializerProvider : BsonSerializationProviderBase
{
public override IBsonSerializer GetSerializer(Type type, IBsonSerializerRegistry registry)
{
if (!type.GetTypeInfo().IsEnum) return null;
var enumSerializerType = typeof(EnumDescriptionSerializer<>).MakeGenericType(type);
var enumSerializerConstructor = enumSerializerType.GetConstructor(new Type[0]);
var enumSerializer = (IBsonSerializer)enumSerializerConstructor?.Invoke(new object[0]);
return enumSerializer;
}
}
public class EnumDescriptionSerializer<TEnum> : StructSerializerBase<TEnum> where TEnum : struct
{
public BsonType Representation => BsonType.String;
public override TEnum Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var valAsString = context.Reader.ReadString();
var enumValue = valAsString.GetValueFromDescription<TEnum>();
return enumValue;
}
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TEnum value)
{
context.Writer.WriteString(value.GetDescription());
}
}
public static class EnumExtensions
{
public enum StringCase
{
/// <summary>
/// The default capitalization
/// </summary>
Default,
/// <summary>
/// Lower Case, ex. i like widgets.
/// </summary>
[Description("Lower Case")]
Lower,
/// <summary>
/// Upper Case, ex. I LIKE WIDGETS.
/// </summary>
[Description("Upper Case")]
Upper,
/// <summary>
/// Lower Camelcase, ex: iLikeWidgets.
/// </summary>
[Description("Lower Camelcase")]
LowerCamel,
/// <summary>
/// Upper Camelcase, ex: ILikeWidgets.
/// </summary>
[Description("Upper Camelcase")]
UpperCamel
}
/// <summary>
/// Get the value of an enum as a string.
/// </summary>
/// <param name="val"> The enum to convert to a <see cref="string"/>. </param>
/// <param name="case"> A <see cref="StringCase"/> indicating which case to return. Valid enumerations are StringCase.Lower and StringCase.Upper. </param>
/// <exception cref="ArgumentNullException"> If the enum is null. </exception>
/// <returns></returns>
public static string GetName<TEnum>(this TEnum val, StringCase #case = StringCase.Default) where TEnum : struct
{
var name = Enum.GetName(val.GetType(), val);
if (name == null) return null;
switch (#case)
{
case StringCase.Lower:
return name.ToLower();
case StringCase.Upper:
return name.ToUpper();
default:
return name;
}
}
/// <summary>
/// Gets the description for the supplied Enum Value.
/// </summary>
/// <param name="val">The value for which to get the description attribute.</param>
/// <returns>The <see cref="string"/> description.</returns>
public static string GetDescription<TEnum>(this TEnum val) where TEnum : struct
{
var fields = val.GetType().GetTypeInfo().GetDeclaredField(GetName(val));
// first try and pull out the EnumMemberAttribute, common when using a JsonSerializer
if (fields.GetCustomAttributes(typeof(EnumMemberAttribute), false).FirstOrDefault() is EnumMemberAttribute jsonAttribute) return jsonAttribute.Value;
// If that doesn't work, do the regular description, that still fails, just return a pretty ToString().
return !(fields.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault() is DescriptionAttribute attribute) ? GetName(val) : attribute.Description;
}
/// <summary>
/// Get the value of an <see cref="Enum"/> based on its description attribute.
/// </summary>
/// <typeparam name="T">The type of the <see cref="Enum"/>.</typeparam>
/// <param name="description">The Description attribute of the <see cref="Enum"/>.</param>
/// <returns>The value of T or default(T) if the description is not found.</returns>
public static T GetValueFromDescription<T>(this string description) where T : struct
{
if (string.IsNullOrWhiteSpace(description)) throw new ArgumentNullException(nameof(description));
var type = typeof(T);
if (!type.GetTypeInfo().IsEnum) throw new ArgumentOutOfRangeException(nameof(T), $"{typeof(T)} is not an Enum.");
var fields = type.GetRuntimeFields();
foreach (var field in fields)
{
if (field.Name == description) return (T)field.GetValue(null);
// first try and pull out the EnumMemberAttribute, common when using a JsonSerializer
if (field.GetCustomAttribute(typeof(EnumMemberAttribute), false) is EnumMemberAttribute jsonAttribute && jsonAttribute.Value == description) return (T)field.GetValue(null);
// If that doesn't work, do the regular description, that still fails, just return a pretty ToString().
if (field.GetCustomAttribute(typeof(DescriptionAttribute), false) is DescriptionAttribute attribute && attribute.Description == description) return (T)field.GetValue(null);
}
throw new Exception($"Failed to parse value {description} into enum {typeof(T)}");
}
}
I wrote a simple test inserti
ng several Foo documents into a collection. This is how they look in the database
> db.enum.find()
{ "_id" : ObjectId("5c76c0240bba918778cc6b7f"), "Enum" : "type_a" }
{ "_id" : ObjectId("5c76c0580bba918778cc6b80"), "Enum" : "type_a" }
{ "_id" : ObjectId("5c76c05d0bba918778cc6b81"), "Enum" : "type_b" }
I also verified that they round-trip correctly. I haven't run any tests beyond some simple code using LINQPad. I believe this is what you are looking for.
ORIGINAL ANSWER
I wrote a custom serializer for this so I could register it and things "just work".
public class EnumAsStringSerializationProvider : BsonSerializationProviderBase
{
public override IBsonSerializer GetSerializer(Type type, IBsonSerializerRegistry registry)
{
if (!type.GetTypeInfo().IsEnum) return null;
var enumSerializerType = typeof(EnumSerializer<>).MakeGenericType(type);
var enumSerializerConstructor = enumSerializerType.GetConstructor(new[] { typeof(BsonType) });
var enumSerializer = (IBsonSerializer) enumSerializerConstructor?.Invoke(new object[] { BsonType.String });
return enumSerializer;
}
}
Then I register it with the BsonSerializer.
var enumAsStringSerializationProvider = new EnumAsStringSerializationProvider();
BsonSerializer.RegisterSerializationProvider(enumAsStringSerializationProvider);
For me, it just works and I don't need to remember to decorate enums.

How to include dynamic math evaluators in UWP project?

I have been using JScript.NET to calculate expressions (and execute input code) in Windows Forms.
Like this:
(55 % 6) + Math.acos(0.4) - ~ 9 * Math.PI + Math.random() = 33.72725296117653
Now I would want to have the same thing on Xamarin Forms, but the library would only work on Android (iOS not tested yet) and UWP project keeps saying that ApplicationException is not found.
Will not update the JScript.NET libraries so the deprecated Vsa Engine is not a problem.
What tried so far
Decompiled the lbrary with ILSpy, but it references mscorlib.dll so much that I gave up.
Looked for Javascript evaluators but they also references mscorlib.dll
I don't know if I should include mscorlib in the project, because Microsoft seems to disallow it.
Any solutions? Thanks in advance.
Edit:
Using JScript 8.0 libraries, if that helps.
If possible, suggest a solution cross-compatible with Win8.1 / WinPhone 8.1 projects too.
You can try using Syncfusion's Calculate library for Xamarin.Forms.
https://www.syncfusion.com/products/xamarin/calculate
It will run in all platforms as you expected.
Eventually I came on to use Jint, which is a Javascript interpreter, free and open-source (no need to worry for licenses yay!) and with a bit of extension methods on Type it seems to work with Win8.1 as well:
#if WINDOWS_APP || WINDOWS_PHONE_APP
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MethodInfos = System.Collections.Generic.IEnumerable<System.Reflection.MethodInfo>;
namespace System.Reflection
{
public static class CustomExtensions
{
public static Assembly Assembly(this Type T) { return T.GetTypeInfo().Assembly; }
public static MethodInfos GetDeclaredMethods(this Type T) { return T.GetTypeInfo().DeclaredMethods; }
public static MethodInfo GetDeclaredMethod(this Type T, string name) { return T.GetTypeInfo().GetDeclaredMethod(name); }
public static bool IsInstanceOfType(this Type T, object o)
{
if (o == null)
return false;
// No need for transparent proxy casting check here
// because it never returns true for a non-rutnime type.
return T.GetTypeInfo().IsAssignableFrom(o.GetType().GetTypeInfo());
}
public static bool IsAssignableFrom(this Type T1, Type T2)
{ return T1.GetTypeInfo().IsAssignableFrom(T2.GetType().GetTypeInfo()); }
public static bool IsEnum(this Type type)
{
return type.GetTypeInfo().IsEnum;
}
public static bool IsGenericType(this Type type)
{
return type.GetTypeInfo().IsGenericType;
}
public static bool IsValueType(this Type type)
{
return type.GetTypeInfo().IsValueType;
}
public static bool HasAttribute<T>(this ParameterInfo member) where T : Attribute
{
return member.GetCustomAttributes<T>().Any();
}
public static Type[] GetGenericArguments(this Type T)
{ return T.GetTypeInfo().GenericTypeArguments; }
public static MethodInfo GetMethod(this Type T, string Name)
{ return T.GetTypeInfo().GetDeclaredMethod(Name); }
public static MethodInfo GetMethod(this Type T, string Name, Type[] Types)
{
var Params = T.GetTypeInfo().GetDeclaredMethods(Name);
foreach (var Item in Params)
{
bool Yes = false;
for (int i = 0; i < Types.Count(); i++)
Yes |= Types[i] == Item.GetParameters()[i].ParameterType;
if (Yes) return Item;
}
return null;
}
public static IEnumerable<Type> GetNestedTypes(this Type T)
{ foreach (TypeInfo Info in T.GetTypeInfo().DeclaredNestedTypes)
yield return Info.AsType();
}
public static IEnumerable<Type> GetNestedTypes(this Type T, BindingFlags Flags)
{
foreach (TypeInfo Info in T.GetTypeInfo().DeclaredNestedTypes)
if(Filter(T.GetTypeInfo(), Flags)) yield return Info.AsType();
}
private static bool Filter(TypeInfo Info, BindingFlags Flags)
{
bool Return = false;
if (Flags.HasFlag(BindingFlags.DeclaredOnly)) Return |= Info.IsNested;
if (Flags.HasFlag(BindingFlags.Instance)) Return |= !(Info.IsAbstract | Info.IsSealed);
if (Flags.HasFlag(BindingFlags.Static)) Return |= Info.IsAbstract | Info.IsSealed;
if (Flags.HasFlag(BindingFlags.Public)) Return |= Info.IsPublic;
if (Flags.HasFlag(BindingFlags.NonPublic)) Return |= Info.IsNotPublic;
return Return;
}
private static bool Filter(MethodInfo Info, BindingFlags Flags)
{
bool Return = false;
if (Flags.HasFlag(BindingFlags.DeclaredOnly)) Return |= Info.IsFamily;
if (Flags.HasFlag(BindingFlags.Instance)) Return |= !Info.IsStatic;
if (Flags.HasFlag(BindingFlags.Static)) Return |= Info.IsStatic;
if (Flags.HasFlag(BindingFlags.Public)) Return |= Info.IsPublic;
if (Flags.HasFlag(BindingFlags.NonPublic)) Return |= !Info.IsPublic;
return Return;
}
public static IEnumerable<Type> GetTypes(this Assembly A)
{ return A.ExportedTypes; }
}
/// <summary>Specifies flags that control binding and the way in which the search for members and types is conducted by reflection.</summary>
[Flags, Runtime.InteropServices.ComVisible(true)]
public enum BindingFlags
{
/// <summary>Specifies no binding flag.</summary>
Default = 0,
/// <summary>Specifies that the case of the member name should not be considered when binding.</summary>
//IgnoreCase = 1,
/// <summary>Specifies that only members declared at the level of the supplied type's hierarchy should be considered. Inherited members are not considered.</summary>
DeclaredOnly = 2,
/// <summary>Specifies that instance members are to be included in the search.</summary>
Instance = 4,
/// <summary>Specifies that static members are to be included in the search.</summary>
Static = 8,
/// <summary>Specifies that public members are to be included in the search.</summary>
Public = 16,
/// <summary>Specifies that non-public members are to be included in the search.</summary>
NonPublic = 32,
/*
/// <summary>Specifies that public and protected static members up the hierarchy should be returned. Private static members in inherited classes are not returned. Static members include fields, methods, events, and properties. Nested types are not returned.</summary>
FlattenHierarchy = 64,
/// <summary>Specifies that a method is to be invoked. This must not be a constructor or a type initializer.</summary>
InvokeMethod = 256,
/// <summary>Specifies that Reflection should create an instance of the specified type. Calls the constructor that matches the given arguments. The supplied member name is ignored. If the type of lookup is not specified, (Instance | Public) will apply. It is not possible to call a type initializer.</summary>
CreateInstance = 512,
/// <summary>Specifies that the value of the specified field should be returned.</summary>
GetField = 1024,
/// <summary>Specifies that the value of the specified field should be set.</summary>
SetField = 2048,
/// <summary>Specifies that the value of the specified property should be returned.</summary>
GetProperty = 4096,
/// <summary>Specifies that the value of the specified property should be set. For COM properties, specifying this binding flag is equivalent to specifying PutDispProperty and PutRefDispProperty.</summary>
SetProperty = 8192,
/// <summary>Specifies that the PROPPUT member on a COM object should be invoked. PROPPUT specifies a property-setting function that uses a value. Use PutDispProperty if a property has both PROPPUT and PROPPUTREF and you need to distinguish which one is called.</summary>
PutDispProperty = 16384,
/// <summary>Specifies that the PROPPUTREF member on a COM object should be invoked. PROPPUTREF specifies a property-setting function that uses a reference instead of a value. Use PutRefDispProperty if a property has both PROPPUT and PROPPUTREF and you need to distinguish which one is called.</summary>
PutRefDispProperty = 32768,
/// <summary>Specifies that types of the supplied arguments must exactly match the types of the corresponding formal parameters. Reflection throws an exception if the caller supplies a non-null Binder object, since that implies that the caller is supplying BindToXXX implementations that will pick the appropriate method.</summary>
ExactBinding = 65536,
/// <summary>Not implemented.</summary>
SuppressChangeType = 131072,
/// <summary>Returns the set of members whose parameter count matches the number of supplied arguments. This binding flag is used for methods with parameters that have default values and methods with variable arguments (varargs). This flag should only be used with <see cref="M:System.Type.InvokeMember(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object,System.Object[],System.Reflection.ParameterModifier[],System.Globalization.CultureInfo,System.String[])" />.</summary>
OptionalParamBinding = 262144,
/// <summary>Used in COM interop to specify that the return value of the member can be ignored.</summary>
IgnoreReturn = 16777216
*/
}
}
#endif
Now I do not have to change my example code and evaluate smoothly on everywhere (even Xamarin.iOS since Jint does not use the DLR or IL emitting methods, which again is another advantage)

InvalidCastException while casting to defined Type C#

I have a Dictionary containing strings as keys, and objects as values in an abstract class.
I have two classes deriving from this abstract class.
One of the deriving classes works perfectly, all configurations and items are loaded and retrievable without issues.
However, the other class is giving me headaches.
When I try to get an object of type "Domain"; I get an invalid cast exception, although I am adding the value to the dictionary as said type.
Here is the code:
public sealed class UserDomainConfig: ConfigParser {
public UserDomainConfig(string configFilePath) : base(configFilePath) { }
public Domain GetConfig(string key) => GetConfig<Domain>(key);
public override bool LoadConfigs() {
return base.LoadConfigs();
}
public UserDomainConfig SetConfig(string key, Domain value) {
base.SetConfig(key, value);
return this;
}
}
public abstract class ConfigParser: IConfig {
/* Snip */
/// <summary>
/// Gets the config.
/// </summary>
/// <returns>The config.</returns>
/// <param name="key">Key.</param>
/// <typeparam name="T">The 1st type parameter.</typeparam>
public virtual T GetConfig<T>(string key) {
object output = null;
try {
if (!configs.TryGetValue(key, out output))
return default(T);
//return (T)output;
//return output as T;
// This is where the exception is occurring.
// I've tried multiple solutions to try to remedy this issue.
return (T)Convert.ChangeType(output, typeof(T));
} catch (InvalidCastException ex) {
logger.Error($"Failed to cast config { key }!");
}
return default(T);
}
/// <summary>
/// Sets the config.
/// </summary>
/// <returns>The config.</returns>
/// <param name="key">Key.</param>
/// <param name="value">Value.</param>
/// <typeparam name="T">The 1st type parameter.</typeparam>
public virtual IConfig SetConfig<T>(string key, T value) {
if (KeyExists(key))
configs.Remove(key);
configs.Add(key, value);
return this;
}
Any ideas on how to fix this, and/or why this isn't working in the first place, although it works like a charm with strings, bools, and ints?
The Convert class only supports simple types, known by .NET, like Int32, String, DateTime. It does not support user defined or complex types like Domain. If you try to convert something to a not-supported type, the method Convert.ChangeType throws an InvalidCastException. The only exception is that it will work if the Original value (output) is already of that desired type; than no actual conversion is needed.
For more information, read: https://msdn.microsoft.com/en-us/library/dtb69x08(v=vs.110).aspx
If you are certain the stored value is of the type Domain, than log more information. Something like this:
logger.Error($"Failed to cast config { key } of type { output.GetType() } to type { typeof(T) }!");
This way you can verify your claim that both types are the same.

Attributes and classes

I'm searching to how can I know inside an attribute definition if the class I apply the attribute to, has another attribute
Example:
[My1Attribute]
public class MyClass
{
[My2Attribute]
int aux{get;set;}
}
internal sealed class My1Attribute : Attribute
{
public My1Attribute
{
// How can I Know if 'MyClass' has My2Attribute applied ???
}
}
The attribute itself will not know about the class to which it's attached. You will need to use some other service/helper function/whatever to pair them up.
However, you might find the following useful:
public static bool HasAttribute<T, TAttribute>() where TAttribute : Attribute
{
return typeof (T).GetCustomAttributes(typeof (TAttribute), true).Any();
}
Edit: For finding attributes on member fields
/// <summary>
/// Returns all the (accessible) fields or properties that for a given type that
/// have the "T" attribute declared on them.
/// </summary>
/// <param name="type">Type object to search</param>
/// <returns>List of matching members</returns>
public static List<MemberInfo> FindMembers<T>(Type type) where T : Attribute
{
return FindMembers<T>(type, MemberTypes.Field | MemberTypes.Property);
}
/// <summary>
/// Returns all the (accessible) fields or properties that for a given type that
/// have the "T" attribute declared on them.
/// </summary>
/// <param name="type">Type object to search</param>
/// <returns>List of matching members</returns>
public static List<MemberInfo> FindMembers<T>(Type type, MemberTypes memberTypesFlags) where T : Attribute
{
const BindingFlags FieldBindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
List<MemberInfo> members = new List<MemberInfo>();
members.AddRange(type.FindMembers(
memberTypesFlags,
FieldBindingFlags,
HasAttribute<T>, // Use delegate from below...
null)); // This arg is ignored by the delegate anyway...
return members;
}
public static bool HasAttribute<T>(MemberInfo mi) where T : Attribute
{
return GetAttribute<T>(mi) != null;
}
public static bool HasAttribute<T>(MemberInfo mi, object o) where T : Attribute
{
return GetAttribute<T>(mi) != null;
}
In this instance, you would need to define your rules about how you determine what members you are going to check. In your example, you're using the attributed decorated on a property, so given that you have an instance of Type for MyClass (e.g. typeof(MyClass)), you can grab the properties:
var property = type.GetProperty("aux", BindingFlags.Instance | BindingFlags.NonPublic);
if (property.IsDefined(typeof(My1Attribute)))
{
// Property has the attribute.
}
(This is assuming you actually want to grab that non-public instance property, if not adjust your BindingFlags).
If you actually want to use the attribute:
var attib = property.GetCustomAttributes(typeof(My1Attribute), false)[0];
// Do something with the attribute instance.
Have you tried Reflection?, plus here's a related question that you might find helpful: How to check if C# class has security attribute used
I am guessing you mean in general find out if any class with MyAttribute1 has My2Attribute (rather than specifically MyClass). The only way I can think of doing it is getting a list of all classes from reflection and iterating through them checking which ones have Attribute1 and then check if they have Attribute2.
I don't think you can do anything clever like automatically retrieve a list of classes with current attribute.

Why can't I define a bit in c#?

Why isn't there a bit structure in C#?
For what's worth, here is a full-fledged bit structure, complete with int and bool casting and arithmetic operations. Probably not perfect, but works fine for me. Enjoy!
/// <summary>
/// Represents a single bit that can be implicitly cast to/from and compared
/// with booleans and integers.
/// </summary>
/// <remarks>
/// <para>
/// An instance with a value of one is equal to any non-zero integer and is true,
/// an instance with a value of zero is equal to the integer zero and is false.
/// </para>
/// <para>
/// Arithmetic and logical AND, OR and NOT, as well as arithmetic XOR, are supported.
/// </para>
/// </remarks>
public struct Bit
{
/// <summary>
/// Creates a new instance with the specified value.
/// </summary>
/// <param name="value"></param>
public Bit(int value) : this()
{
Value = value == 0 ? 0 : 1;
}
/// <summary>
/// Gets the value of the bit, 0 or 1.
/// </summary>
public int Value { get; private set; }
#region Implicit conversions
public static implicit operator Bit(int value)
{
return new Bit(value);
}
public static implicit operator int(Bit value)
{
return value.Value;
}
public static implicit operator bool(Bit value)
{
return value.Value == 1;
}
public static implicit operator Bit(bool value)
{
return new Bit(value ? 1 : 0);
}
#endregion
#region Arithmetic operators
public static Bit operator |(Bit value1, Bit value2)
{
return value1.Value | value2.Value;
}
public static Bit operator &(Bit value1, Bit value2)
{
return value1.Value & value2.Value;
}
public static Bit operator ^(Bit value1, Bit value2)
{
return value1.Value ^ value2.Value;
}
public static Bit operator ~(Bit value)
{
return new Bit(value.Value ^ 1);
}
public static Bit operator !(Bit value)
{
return ~value;
}
#endregion
#region The true and false operators
public static bool operator true(Bit value)
{
return value.Value == 1;
}
public static bool operator false(Bit value)
{
return value.Value == 0;
}
#endregion
#region Comparison operators
public static bool operator ==(Bit bitValue, int intValue)
{
return
(bitValue.Value == 0 && intValue == 0) ||
(bitValue.Value == 1 && intValue != 0);
}
public static bool operator !=(Bit bitValue, int intValue)
{
return !(bitValue == intValue);
}
public override bool Equals(object obj)
{
if(obj is int)
return this == (int)obj;
else
return base.Equals(obj);
}
#endregion
}
It is called a boolean. At least, it would serve the basic function, right? You don't twiddle bits that often in C# (at least, I don't), and if you need to you can use the built in operations.
There is a BitArray class..
What would you want to do with it? Bear in mind that the CLR isn't going to try to pack multiple variables into a byte, so having one on its own would be no more useful than boolean. If you wanted to have a collection of them - well, that's what BitArray is for, as David pointed out.
If we did have a Bit structure, I suspect people would expect multiple Bit variables to be packed efficiently in memory - by not having the type in the first place, we avoid that expectation and lead people towards other solutions such as BitArray.
If you have a collection of bit flags, then using enums (with falgs attribute) and integers work a long way.
Though maybe there are rare exceptions, computers are not designed or intended to manipulate or allocate individual bits. Even at the lowest levels (assembly or pure machine language), you will not be able to allocate or access an individual bit. You have the same tools available in this regard as you have from any programming level: bytes and bitwise operations.
Along with the BitArray class already mentioned there is a also the more efficient BitVector32 Structure.
BitVector32 is more efficient than BitArray for Boolean values and
small integers that are used internally. A BitArray can grow
indefinitely as needed, but it has the memory and performance overhead
that a class instance requires. In contrast, a BitVector32 uses only
32 bits.
Keep in mind you are limited to 32 values.
Examples of BitVector32 usage at Dotnetpearls.com
You can do this now in C# 7.0!
public const int One = 0b0001;
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#numeric-literal-syntax-improvements

Categories