I've got a generic function to parse an object into a generic Enum.
However, I'm running into an issue when trying to safely parse an int into a [Flags] Enum.
Directly using Enum.ToObject() works to parse valid combinations, but will just return the original value if there isn't a flag combination.
Additionally, when there's no explicit enum member for a combination of flags, Enum.ToName() and Enum.IsDefined() don't return helpful values.
For Example:
[Flags]
public enum Color
{
None = 0,
Red = 1,
Green = 2,
Blue = 4,
}
// Returns 20
Enum.ToObject(typeof(Color), 20)
// Returns ""
Enum.ToName(typeof(Color), 3)
// Returns false
Enum.IsDefined(typeof(Color), 3)
I've written a function that I think technically works, but it seems like there has to be a better way to do this.
My Function:
public static T ParseEnumerator<T>(object parseVal, T defaultVal) where T : struct, IConvertible
{
Type ttype = typeof(T);
if (!ttype.IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
bool isFlag = ttype.GetCustomAttribute(typeof(FlagsAttribute)) != null;
try
{
if (parseVal == null)
{
return defaultVal;
}
else if (parseVal is T)
{
return (T)parseVal;
}
else if (parseVal is string)
{
return (T)Enum.Parse(ttype, parseVal.ToString(), true);
}
//**************** The section at issue **********************************/
else if (isFlag && parseVal is int)
{
List<string> flagsList = new List<string>();
int maxVal = 0;
//Loop through each bit flag
foreach (var val in Enum.GetValues(ttype))
{
if (CountBits((int)val) == 1)
{
if ((int)val > maxVal)
maxVal = (int)val;
// If the current bit is set, add the flag to the result
if (((int)parseVal & (int)val) == (int)val)
{
string enumName = Enum.GetName(ttype, val);
if (!string.IsNullOrEmpty(enumName))
flagsList.Add(enumName);
}
}
}
// Is the value being parsed over the highest bitwise value?
if ((int)parseVal >= (maxVal << 1))
return defaultVal;
else
return (T)Enum.Parse(ttype, string.Join(",", flagsList));
}
//************************************************************************/
else
{
string val = Enum.GetName(ttype, parseVal);
if (!string.IsNullOrEmpty(val))
return (T)Enum.ToObject(ttype, parseVal);
else
return defaultVal;
}
}
catch
{
return defaultVal;
}
}
Is there something I'm missing? Or is there another way to parse these values safely?
Any help is appreciated, thanks!
-MM
Since your generic function has to know the Enum type to begin with, you can just scrap the function and use basic casting instead.
using System;
namespace SO_58455415_enum_parsing {
[Flags]
public enum CheeseCharacteristics {
Yellow = 1,
Mouldy = 2,
Soft = 4,
Holed = 8
}
public static class Program {
static void Main(string[] args) {
CheeseCharacteristics cc = (CheeseCharacteristics)12;
Console.WriteLine(cc);
}
}
}
If all you want to know is if you have a value that can be created using the enum flags.. that's pretty easy, as long as we can assume that each flag is "sequential" (e.g. there are no gaps between the flags). All numbers between 1 and the sum of all flag values can be made by some combination of flags. You can simply sum the flag values together and compare that to your question value.
public static bool IsValidFlags<T>(int checkValue) where T:Enum {
int maxFlagValue = ((int[])Enum.GetValues(typeof(T))).Sum();
return (0 < checkValue) && (checkValue <= maxFlagValue);
}
For future reference, you can constrain your generic parameter to an enum:
void fx<T> () where T:Enum { }
How can I change this method's return type based on the value of returnType?
I want to return ints, floats, and decimals, without creating separate methods for each one. Specifically, how can I change the decimal in the first line based on the value of returnType??
public static decimal RequestNumber(string returnType)
{
Console.WriteLine(inputRequest);
decimal result;
switch(returnType)
case decimal:
bool parsed = decimal.TryParse(Console.ReadLine(), out result);
case int:
bool parsed = int.TryParse(Console.ReadLine(), out result);
case single:
bool parsed = single.TryParse(Console.ReadLine(), out result);
return result;
}
Any help would be much appreciated!
You could use object type and then cast the return result when calling;
private static object duo(string req)
{
if (req == "Y")
{
string s = "Type String";
return s;
}
else
{
List < string > l = new List<string> { "Type", "List" };
return l;
}
}
Then to use it:
List<string> res = (List<string>)duo("H");
For example,
I have input parameter of type object. And I know that this parameter can store one of value type int, float, double(boxed value) etc. But I don't know which value type will come to this method. And I want check if boxed value type empty or not.
Like this piece of code:
bool IsEmpty(object boxedProperty)
{
return boxedProperty == default(typeof(boxedProperty))
}
I understand, I can do this:
bool IsEmpty(object boxedProperty)
{
return boxedProperty is int && boxedProperty == default(int)
|| boxedProperty is float ....
}
But it looks like dirty solution. How do this better?
I guess something like this can give you a result for reference + boxed value types.
public bool IsDefaultValue(object o)
{
if (o == null)
return true;
var type = o.GetType();
return type.IsValueType && o.Equals(Activator.CreateInstance(type));
}
object i = default(int);
object j = default(float);
object k = default(double);
object s = default(string);
object i2 = (int)2;
object s2 = (string)"asas";
var bi = IsDefaultValue(i); // true
var bj = IsDefaultValue(j); // true
var bk = IsDefaultValue(k); // true
var bs = IsDefaultValue(s); // true
var bi2 = IsDefaultValue(i2); // false
var bs2 = IsDefaultValue(s2); // false
If you are shure you have a value type, then use this method:
public bool IsDefaultBoxedValueType(object o)
{
return o.Equals(Activator.CreateInstance(o.GetType()));
}
As others have pointed out the only real way to do it is to create an instance of the type and then compare it. (see also how to get the default value of a type if the type is only known as System.Type? and Default value of a type at Runtime)
You can cache the results so you only have to create a default instance 1x type. This can increase efficiency if you have to call the check many times. I used a static method and dictionary (its not thread safe) but you could change it to instance level if you wanted.
static IDictionary<Type, object> DefaultValues = new Dictionary<Type, object>();
static bool IsBoxedDefault(object boxedProperty)
{
if (boxedProperty == null)
return true;
Type objectType = boxedProperty.GetType();
if (!objectType.IsValueType)
{
// throw exception or something else?? Up to how you want this to behave
return false;
}
object defaultValue = null;
if (!DefaultValues.TryGetValue(objectType, out defaultValue))
{
defaultValue = Activator.CreateInstance(objectType);
DefaultValues[objectType] = defaultValue;
}
return defaultValue.Equals(boxedProperty);
}
Test code
static void Test()
{
Console.WriteLine(IsBoxedDefault(0)); // true
Console.WriteLine(IsBoxedDefault("")); // false (reference type)
Console.WriteLine(IsBoxedDefault(1));// false
Console.WriteLine(IsBoxedDefault(DateTime.Now)); // false
Console.WriteLine(IsBoxedDefault(new DateTime())); // true
}
Looks to my like a generic function is a fine way to go. Something similar to:
static void Main(string[] args)
{
object obj1 = null;
object obj2 = "Assigned value";
Console.WriteLine(string.Format("IsEmpty(obj1) --> {0}", IsEmpty(obj1)));
Console.WriteLine(string.Format("IsEmpty(obj2) --> {0}", IsEmpty(obj2)));
Console.ReadLine();
}
private static bool IsEmpty<T>(T boxedProperty)
{
T defaultProperty = default(T);
return ReferenceEquals(boxedProperty, defaultProperty);
}
Outputs:
IsEmpty(obj1) --> True
IsEmpty(obj1) --> False
In the stub below how do I pass in (MyEnum) as a parameter such that I can use this procedure with any enum?
public static Enum Proc(this Enum e)
{
Int32 i = (Int32)(MyEnum)e;
...
Here is the solution I have come up with that works:
public static Enum Next(this Enum e, Type eT)
{
Int32 i = (Int32)(Object)e;
return (Enum)Enum.Parse(eT, Enum.GetName(eT, Enum.GetName(eT, ++i) == null? i = 0 : i));
}
This solution isn't ideal because I have to do this to get the next value:
MyEnum e = (MyEnum)e.Next(typeof(MyEnum));
I'd rather just do
MyEnum e = e.Next(typeof(MyEnum));
Or even better:
MyEnum e = e.Next();
Anyone who can provide the simple solution can have the point.
Also the code I've written above runs fine in LinqPad but only compiles in WP7 and then throws an exception when I run it (InvalidProgramException).
Here's a function that will cycle through the values of any enum:
static public Enum Cycle(this Enum e)
{
bool found = false;
Enum first = null;
foreach (Enum i in Enum.GetValues(e.GetType()))
{
if (first == null)
first = i;
if (found)
return i;
found = e.Equals(i);
}
if (found)
return first;
return null;
}
For versions of C# that don't have Enum.GetValues, you'll have to use a method like this which only works for enums whose values start at 0 and increment by 1:
static public Enum Cycle(this Enum e)
{
var i = ((IConvertible)e).ToInt64(null) + 1;
var eT = e.GetType();
var next = Enum.GetName(eT, i);
return (Enum)Enum.Parse(eT, next ?? Enum.GetName(eT, 0), false);
}
Use it like:
var nextEnum = (MyEnum)curEnum.Cycle();
Edit: I updated this to return the next enum in the list, strongly typed, regardless of what the numbering of the enum values may be. I'm able to compile and run this under .NET 4 and haven't tried it on WP7, but I don't think I'm using anything that's missing/disabled in SL/WP7.
public static T Next<T>(this T e) where T : struct
{
var t = typeof(T);
if (!t.IsEnum) throw new ArgumentException("T must be an enumerated type");
if (!Enum.IsDefined(t, e)) throw new ArgumentException();
var intValue = (int)t.GetField(e.ToString()).GetValue(null);
var enumValues = t.GetFields(BindingFlags.Public | BindingFlags.Static).Select(x => x.GetValue(null));
var next = (T?)enumValues.Where(x => (int)x > intValue).Min();
if (next.HasValue)
return next.Value;
else
return (T)enumValues.Min();
}
It can be used as simply as:
var nextE = e.Next();
Is there a way to get all types used inside C# method?
For example,
public int foo(string str)
{
Bar bar = new Bar();
string x = "test";
TEST t = bar.GetTEST();
}
would return: Bar, string and TEST.
All I can get now is the method body text using EnvDTE.CodeFunction. Maybe there is a better way to achieve it than trying to parse this code.
I'm going to take this opportunity to post up a proof of concept I did because somebody told me it couldn't be done - with a bit of tweaking here and there, it'd be relatively trivial to extend this to extract out all referenced Types in a method - apologies for the size of it and the lack of a preface, but it's somewhat commented:
void Main()
{
Func<int,int> addOne = i => i + 1;
Console.WriteLine(DumpMethod(addOne));
Func<int,string> stuff = i =>
{
var m = 10312;
var j = i + m;
var k = j * j + i;
var foo = "Bar";
var asStr = k.ToString();
return foo + asStr;
};
Console.WriteLine(DumpMethod(stuff));
Console.WriteLine(DumpMethod((Func<string>)Foo.GetFooName));
Console.WriteLine(DumpMethod((Action)Console.Beep));
}
public class Foo
{
public const string FooName = "Foo";
public static string GetFooName() { return typeof(Foo).Name + ":" + FooName; }
}
public static string DumpMethod(Delegate method)
{
// For aggregating our response
StringBuilder sb = new StringBuilder();
// First we need to extract out the raw IL
var mb = method.Method.GetMethodBody();
var il = mb.GetILAsByteArray();
// We'll also need a full set of the IL opcodes so we
// can remap them over our method body
var opCodes = typeof(System.Reflection.Emit.OpCodes)
.GetFields()
.Select(fi => (System.Reflection.Emit.OpCode)fi.GetValue(null));
//opCodes.Dump();
// For each byte in our method body, try to match it to an opcode
var mappedIL = il.Select(op =>
opCodes.FirstOrDefault(opCode => opCode.Value == op));
// OpCode/Operand parsing:
// Some opcodes have no operands, some use ints, etc.
// let's try to cover all cases
var ilWalker = mappedIL.GetEnumerator();
while(ilWalker.MoveNext())
{
var mappedOp = ilWalker.Current;
if(mappedOp.OperandType != OperandType.InlineNone)
{
// For operand inference:
// MOST operands are 32 bit,
// so we'll start there
var byteCount = 4;
long operand = 0;
string token = string.Empty;
// For metadata token resolution
var module = method.Method.Module;
Func<int, string> tokenResolver = tkn => string.Empty;
switch(mappedOp.OperandType)
{
// These are all 32bit metadata tokens
case OperandType.InlineMethod:
tokenResolver = tkn =>
{
var resMethod = module.SafeResolveMethod((int)tkn);
return string.Format("({0}())", resMethod == null ? "unknown" : resMethod.Name);
};
break;
case OperandType.InlineField:
tokenResolver = tkn =>
{
var field = module.SafeResolveField((int)tkn);
return string.Format("({0})", field == null ? "unknown" : field.Name);
};
break;
case OperandType.InlineSig:
tokenResolver = tkn =>
{
var sigBytes = module.SafeResolveSignature((int)tkn);
var catSig = string
.Join(",", sigBytes);
return string.Format("(SIG:{0})", catSig == null ? "unknown" : catSig);
};
break;
case OperandType.InlineString:
tokenResolver = tkn =>
{
var str = module.SafeResolveString((int)tkn);
return string.Format("('{0}')", str == null ? "unknown" : str);
};
break;
case OperandType.InlineType:
tokenResolver = tkn =>
{
var type = module.SafeResolveType((int)tkn);
return string.Format("(typeof({0}))", type == null ? "unknown" : type.Name);
};
break;
// These are plain old 32bit operands
case OperandType.InlineI:
case OperandType.InlineBrTarget:
case OperandType.InlineSwitch:
case OperandType.ShortInlineR:
break;
// These are 64bit operands
case OperandType.InlineI8:
case OperandType.InlineR:
byteCount = 8;
break;
// These are all 8bit values
case OperandType.ShortInlineBrTarget:
case OperandType.ShortInlineI:
case OperandType.ShortInlineVar:
byteCount = 1;
break;
}
// Based on byte count, pull out the full operand
for(int i=0; i < byteCount; i++)
{
ilWalker.MoveNext();
operand |= ((long)ilWalker.Current.Value) << (8 * i);
}
var resolved = tokenResolver((int)operand);
resolved = string.IsNullOrEmpty(resolved) ? operand.ToString() : resolved;
sb.AppendFormat("{0} {1}",
mappedOp.Name,
resolved)
.AppendLine();
}
else
{
sb.AppendLine(mappedOp.Name);
}
}
return sb.ToString();
}
public static class Ext
{
public static FieldInfo SafeResolveField(this Module m, int token)
{
FieldInfo fi;
m.TryResolveField(token, out fi);
return fi;
}
public static bool TryResolveField(this Module m, int token, out FieldInfo fi)
{
var ok = false;
try { fi = m.ResolveField(token); ok = true; }
catch { fi = null; }
return ok;
}
public static MethodBase SafeResolveMethod(this Module m, int token)
{
MethodBase fi;
m.TryResolveMethod(token, out fi);
return fi;
}
public static bool TryResolveMethod(this Module m, int token, out MethodBase fi)
{
var ok = false;
try { fi = m.ResolveMethod(token); ok = true; }
catch { fi = null; }
return ok;
}
public static string SafeResolveString(this Module m, int token)
{
string fi;
m.TryResolveString(token, out fi);
return fi;
}
public static bool TryResolveString(this Module m, int token, out string fi)
{
var ok = false;
try { fi = m.ResolveString(token); ok = true; }
catch { fi = null; }
return ok;
}
public static byte[] SafeResolveSignature(this Module m, int token)
{
byte[] fi;
m.TryResolveSignature(token, out fi);
return fi;
}
public static bool TryResolveSignature(this Module m, int token, out byte[] fi)
{
var ok = false;
try { fi = m.ResolveSignature(token); ok = true; }
catch { fi = null; }
return ok;
}
public static Type SafeResolveType(this Module m, int token)
{
Type fi;
m.TryResolveType(token, out fi);
return fi;
}
public static bool TryResolveType(this Module m, int token, out Type fi)
{
var ok = false;
try { fi = m.ResolveType(token); ok = true; }
catch { fi = null; }
return ok;
}
}
If you can access the IL for this method, you might be able to do something suitable. Perhaps look at the open source project ILSpy and see whether you can leverage any of their work.
As others have mentioned, if you had the DLL you could use something similar to what ILSpy does in its Analyze feature (iterating over all the IL instructions in the assembly to find references to a specific type).
Otherwise, there is no way to do it without parsing the text into a C# Abstract Syntax Tree, AND employing a Resolver - something that can understand the semantics of the code well enough to know if "Bar" in your example is indeed a name of a type that is accessible from that method (in its "using" scope), or perhaps the name of a method, member field, etc... SharpDevelop contains a C# parser (called "NRefactory") and also contains such a Resolver, you can look into pursuing that option by looking at this thread, but beware that it is a fair amount of work to set it up to work right.
I just posted an extensive example of how to use Mono.Cecil to do static code analysis like this.
I also show a CallTreeSearch enumerator class that can statically analyze call trees, looking for certain interesting things and generating results using a custom supplied selector function, so you can plug it with your 'payload' logic, e.g.
static IEnumerable<TypeUsage> SearchMessages(TypeDefinition uiType, bool onlyConstructions)
{
return uiType.SearchCallTree(IsBusinessCall,
(instruction, stack) => DetectTypeUsage(instruction, stack, onlyConstructions));
}
internal class TypeUsage : IEquatable<TypeUsage>
{
public TypeReference Type;
public Stack<MethodReference> Stack;
#region equality
// ... omitted for brevity ...
#endregion
}
private static TypeUsage DetectTypeUsage(
Instruction instruction, IEnumerable<MethodReference> stack, bool onlyConstructions)
{
TypeDefinition resolve = null;
{
TypeReference tr = null;
var methodReference = instruction.Operand as MethodReference;
if (methodReference != null)
tr = methodReference.DeclaringType;
tr = tr ?? instruction.Operand as TypeReference;
if ((tr == null) || !IsInterestingType(tr))
return null;
resolve = tr.GetOriginalType().TryResolve();
}
if (resolve == null)
throw new ApplicationException("Required assembly not loaded.");
if (resolve.IsSerializable)
if (!onlyConstructions || IsConstructorCall(instruction))
return new TypeUsage {Stack = new Stack<MethodReference>(stack.Reverse()), Type = resolve};
return null;
}
This leaves out a few details
implementation of IsBusinessCall, IsConstructorCall and TryResolve as these are trivial and serve as illustrative only
Hope that helps
The closest thing to that that I can think of are expression trees. Take a look at the documentation from Microsoft.
They are very limited however and only work on simple expressions and not full methods with statement bodies.
Edit: Since the intention of the poster was to find class couplings and used types, I would suggest using a commercial tool like NDepend to do the code analysis as an easy solution.
This definitely cannot be done from reflection (GetMethod(), Expression Trees, etc.). As you mentioned, using EnvDTE's CodeModel is an option since you get line-by-line C# there, but using it outside Visual Studio (that is, processing an already existing function, not in your editor window) is nigh-impossible, IMHO.
But I can recommend Mono.Cecil, which can process CIL code line-by-line (inside a method), and you can use it on any method from any assembly you have reference to. Then, you can check every line if it is a variable declaration (like string x = "test", or a methodCall, and you can get the types involved in those lines.
With reflection you can get the method. This returns a MethodInfo object, and with this object you cannot get the types which are used in the method. So I think the answer is that you cannot get this native in C#.