I'm basically saving and loading values into an array to feed into a JSON library, and I'm just looking for a more elegant way to do this:
class properties to array
return new object[] { path, pathDir, name };
array to class properties
c.path = values[0];
c.pathDir = values[1];
c.name = values[2];
Simple solutions that ideally do not require additional run time overheads such as Reflection are appreciated.
Can I do something like this?
c.{path, pathDir, name} = values[0...2]
Edit: I'm specifically asking for arrays. I know about serialization and JSON and Protobuf and everything else everyone is suggesting.
Would this not do the trick?
return new {path= "/Some/Path", pathDir= "SiteRoot", name="MyPath"}
Edit:
//Mock function to simulate creating 5 objects with 'CreateArrayOb' function
public void CreatingObjects()
{
var lst = new List<object>();
for (var x = 0; x < 5; x++)
{
lst.Add(CreateArrayOb(new string[] {"Path" + x, "Dir" + x, "Path" + x}));
}
}
public object CreateArrayOb(object[] vals)
{
if (vals != null && vals.Any())
{
//Switch cases in the event that you would like to alter the object type returned
//based on the number of parameters sent
switch (vals.Count())
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
return new { path = vals.ElementAt(0), pathDir = vals.ElementAt(1), name = vals.ElementAt(2) };
}
}
return null;
}
Related
So I have a program for this class where I'm supposed to allow the user to select a data type like byte, int, short, long, and etc. And then I am supposed to validate and make sure that the numbers they enter for the math problem aren't outside of the bounds of the data type they selected. Right now I'm using a bunch of if statements for each individual data type, and checking if it's above MaxValue or below MinValue. However, there has to be a better way to do this, right?
My current code is like this (numType is a byte set to the value of a constant when the button is pressed):
if(numType = BYTE){
if(leftNum > byte.MaxValue){
errorsEncountered = true;
returnString = returnString + "Left number must not be more than " +
byte.MaxValue.ToString() + " for a byte.\n";
}
if(leftNum < byte.MinValue){
errorsEncountered = true;
returnString = returnString + "Left number must not be less than " +
byte.MinValue.ToString() + " for a byte.\n";
... (so on and so forth)
}
However I'd like to think that you could instead use something like a variable to record the data type and use that instead. So lets say that you have an array of each potential value of numType (1-7 in this case). Would there be a way to do something like this?
byte numType = 8; // Will never be returned as this, an error is output for this value immediately.
const byte BYTE = 0;
const byte SHORT = 1;
const byte INT = 2;
const byte LONG = 3;
const byte FLOAT = 4;
const byte DOUBLE = 5;
const byte DECIMAL = 6;
string[] dataTypes = {"byte", "short", "int", "long", "float", "double", "decimal"};
if(leftNum > dataTypes[numType].MaxValue) {
errorsEncountered = true;
returnString = "Left number must not be more than " +
dataTypes[numType].MaxValue.ToString() + " for a " + dataTypes[numType] + ".";
}
if(leftNum < dataTypes[numType].MinValue) {
errorsEncountered = true;
returnString = "Left number must not be more than " +
dataTypes[numType].MinValue.ToString() + " for a " + dataTypes[numType] + ".";
}
I know my demonstration is incredibly simplistic but I genuinely don't know how better to describe what I'm trying to do. Thank you for any help you can provide.
Edit: Honestly it seems I'm a bit out of my depth here. I have no clue what most of these solutions are actually doing, and I've come out of this with the impression that I should probably just work on learning the language as a whole.
You can keep a dictionary of all the types you want to use with the string you want the user to type in to refer to that type, then use reflection to call TryParse and MinValue/MaxValue if needed.
Something like this:
public static readonly Dictionary<string, Type> aliases = new() {
{ "byte", typeof(byte) },
{ "short" , typeof(short) },
{ "int" , typeof(int) },
{ "long" , typeof(long) },
{ "float" , typeof(float) },
{ "double" , typeof(double) },
{ "decimal" , typeof(decimal) }
};
static void Main() {
Type type;
while (true) {
Console.WriteLine("Enter the type:");
var selectedType = Console.ReadLine().Trim();
if (!aliases.TryGetValue(selectedType, out type)) {
Console.WriteLine("You did it wrong");
continue;
}
break;
}
while (true) {
Console.WriteLine("Type a value:");
var value = Console.ReadLine().Trim();
// Create an instance of whatever type we're using
object result = Activator.CreateInstance(type);
// Get a reference to the TryParse method for this type
var tryParseMethod = type.GetMethod("TryParse", new[] { typeof(string), type.MakeByRefType() });
// Call TryParse
if (tryParseMethod.Invoke(null, new[] { value, result }) is bool success && success) {
Console.WriteLine("You did it right!");
break;
} else {
// TryParse failed, so show the user the min/max values
var minValueProp = type.GetField("MinValue");
var maxValueProp = type.GetField("MaxValue");
Console.WriteLine($"You did it wrong. Enter a value between {minValueProp.GetValue(result)} and {maxValueProp.GetValue(result)}");
continue;
}
}
}
For example:
Enter the type:
byte
Type a value:
-1
You did it wrong. Enter a value between 0 and 255
Type a value:
1
You did it right!
A bit more of code would be helpful, for instance how leftNum and numType are declared.
Let's try to help anyway. You can try a polymorphic approach.
It may be overkill, but it's a nice exercise:
Create an interface, let's say ITypeValidator
Create the implementations of such Interface, i.e. IntegerValidator : ITypeValidator
Have a Dictionary containing your validators and their respective type Dictionary<byte, ITypeValidator>
Initialize your types in your Dictionary.
Sample:
internal class Program
{
static void Main(string[] args)
{
var myTypes = GetTypesImplementingInterface();
byte numType = 2;
object leftNum = 3;
var validator = myTypes[numType];
var result = validator.Validate(leftNum);
}
public static Dictionary<byte, ITypeValidator> GetTypesImplementingInterface()
{
// Fancy approach would be to use reflection to scan the Assembly
// for implementations of our interface and automatically
// instantiate and fill in the Dictionary
return new Dictionary<byte, ITypeValidator>()
{
{ 2, new IntValidator() }
};
}
public interface ITypeValidator
{
byte TypeNumber { get; } // Tip: this helps with the Reflection approach
ValidationResult Validate(object number);
}
public class ValidationResult
{
public bool HasError { get; set; }
public List<string> ErrorMessages { get; set; }
}
public class IntValidator : ITypeValidator
{
public byte TypeNumber => 2;
public ValidationResult Validate(object number)
{
// do your things
return new ValidationResult();
}
}
}
If your validations are always the same (min and max), you can also think of adding a base class, with abstract Minimum and Maximum properties and a base validation method. So for each type, you just need to implement the TypeNumber, Min and Max values.
Expected result :
List<something> obj = new List<something>(); //something is i need.
string[] val = new string[] {"hi","20"}; //here I used static but input data fetch from CSV file. So we don't know when which type of data will come?.
int intval;
for(int i=0;i<val.Length;i++)
{
if(int.TryParse(val[i],out intval)
{
obj.add(intval); //here I face the error "Cannot implicitly convert int to string"
}
else
{
obj.add(val[i]);
}
}
I need to add int value and also string value into the same list. But The condition is Developer don't know when which type of value will come. So here I used TryParse to convert values and store into list.
How to declare a list or any other methods are there?
Note: Don't use Class to declare field and define like List<classname> val = new List<classname>();
Not sure why you want to do this but I think the code below is what you're looking for. I suppose you can later check if each list value typeof is string/int but why store multi value types in one list like this?
string[] val = new string[] { "hi", "20" };
List<object> objs = val.Select(x =>
{
if (int.TryParse(x, out var intval))
return (object)intval;
else
return (object)x;
}).ToList();
If you just need to store all the results that you get to a single list without caring about the type then dont Parse to int type like
for (int i = 0; i < val.Length; i++)
{
//simply add the
obj.add(val[i]);
}
Just use a List<object>. Every type ultimately derives from object:
List<object> obj = new List<object>();
string[] val = new string[] {"hi","20"};
for(int i = 0; i < val.Length; i++)
{
if(int.TryParse(val[i], out var intval)
{
obj.add(intval);
}
else
{
obj.add(val[i]);
}
}
what is such method in the picture bellow and how can I make such one?
I searched internet a lot and did not find any thing. tried many thing like attribute method or property method bu nothing founded.
In-fact my problem is that I want to make a method to work like this and the input parameters be optional.
My Questions Image
this is my code bellow (Except panel others are enum type) :
public static void Reset(System.Windows.Forms.Panel panel, formulaType formulaType, ShalvarType shalvarType = 0
, DamanType damanType = 0, YaqeType yaqeType = 0, BalataneType balataneType = 0, AstinType astinType = 0)
{
object[,] collcetion = null;
switch (formulaType)
{
case formulaType.Shalvar:
collcetion = shalvarFurmula(shalvarType);
break;
case formulaType.Daman:
collcetion = damanFurmula(damanType);
break;
case formulaType.Yaqe:
collcetion = yaqeFurmula(yaqeType);
break;
case formulaType.Balatane:
collcetion = balataneFurmula(balataneType);
break;
case formulaType.Astin:
collcetion = astinFurmula(astinType);
break;
}
//System.Windows.Forms.TextBox
for (int i = 0; i < collcetion.Length; i++)
{
if (panel.Controls[collcetion[i, 0].ToString()].GetType().ToString() == "System.Windows.Forms.TextBox")
{
panel.Controls[collcetion[i, 0].ToString()].Text = collcetion[i, 1].ToString();
}
else
{
System.Windows.Forms.NumericUpDown num = panel.Controls[collcetion[i, 0].ToString()] as System.Windows.Forms.NumericUpDown;
num.Value = Convert.ToDecimal(collcetion[i, 1]);
}
}
}
I want to have panel and formula type but from the third one to end be like that. in fact I give the enum type the way like picture.
By the way the code i send is not complete yet.
Thankx
What your image refers to are an Attribute's optional properties, they are defined as:
public class MyAttribute : Attribute
{
public string SomeData { get; set; }
}
What you want is to use optional parameters. You achieve this like this:
public void DoSomething(string data = "", int age = 0) // data will be empty if no value is given
{
}
And you can then call this method with both:
DoSomething();
DoSomething("some data");
DoSomething(age: 10);
I have the following code:
switch (pk.Substring(2, 2))
{
case "00":
ViewBag.Type = _reference.Get("14", model.Type).Value;
break;
case "01":
ViewBag.Type = _reference.Get("18", model.Type).Value;
break;
}
It does the job but does not look very clean to me. Is there some way I could make this code a bit smaller. I was thinking to just have the number 14 or 18 as a variable but I am not sure the best way to code if I should use if-else or some other way.
You could use a static dictionary as a map instead of a switch-statement.
static readonly Dictionary<string, string> map = new Dictionary<string, string> {
{ "00", "14" },
{ "01", "18" },
// ... more ...
};
// ... in your method ...
string str = pk.Substring(2, 2);
string val;
if (!map.TryGetValue(str, out val))
{
// Handle error, like in the "default:" case of the switch statement
}
else
{
ViewBag.Type = _reference.Get(val, model.Type).Value;
}
However, I would only do this, if there are really a lot of mappings that maybe can even be "read" from an external source like a configuration file.
Also note, that if the "key" is really a consecutive sequence of integers starting at 0, you might be able to use an array, where the "key" is simply the index into it.
static readonly string[] map = new string[] {
"14", "18", ...
};
int index = Int32.Parse(pk.Substring(2, 2)); // Error handling elided.
if (index < 0 || index > map.Length)
{
// Handle error, like in the "default:" case of the switch statement
}
else
{
ViewBag.Type = _reference.Get(map[index], model.Type).Value;
}
Otherwise rather stay with an explicit switch statement (possibly factoring out the assignment for more terse code):
string val;
switch (pk.Substring(2, 2))
{
case "00":
val = "14";
break;
case "01":
val = "18";
break;
// ... more ...
default:
// Error handling for unknown switch-value.
break;
}
ViewBag.Type = _reference.Get(val, model.Type).Value;
It seems that there is some relationship between "00"->"14" and "01"->"18". I believe this relationship results from the business logic. You should wrap the logic and make the code in your controller clear. Finally the code in the controller should look like:
public ActionResult MyAction()
{
//some code
ViewBag.Type = TypeProvider.GetType(pk, model.Type);
//return something
}
class TypeProvider
{
Dictionary<string, string> relations = ...
//a dictionary stores "00"->"14" logics
public static SomeType GetType(string pk, Type modelType)
{
return _reference.Get(relations[pk.SubString(2,2)], modelType).Value;
}
}
var data = pk.Substring(2, 2);
var choice = data == "00" ? "14" : (data=="01"?"18":"");
if (choice != string.Empty) ViewBag.Type = _reference.Get(choice, model.Type).Value;
I use mapping extensions fot that kind of code:
ViewBag.Type = pk.Substring(2, 2)
.Map("00", x => GetViewBagValue("14"))
.Map("01", x => GetViewBagValue("18"))
and in your case this method:
private ViewBagValue GetViewBagValue(string value)
{
return _reference.Get(value, model.Type).Value;
}
I use this. You could easily change it to generic or use e.g. object[] instead. Not super efficient, but very compact:
public static class Util {
public static string Switch(string value, params string[] nameValues) {
for (int x = 0; x < nameValues.Length; x += 2) {
if (nameValues[x] == value) {
return nameValues[x + 1];
}
}
return string.Empty;
}
}
Then just call that like this:
var res = Util.Switch("test2", "test1", "res1", "test2", "res2");
Best of luck!
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#.