I am working in .cs file and I need to see the output of some object/variable executed by the c# program. I will use that for debbuging purposes each time.
For example, in the code below, I need to see the output of the variable DataNaiss (type,number of rows,all elements included...).
var DataNaiss = engine.Evaluate("DataNaiss=DataIns[which(cond1 & DataIns$Id %in% ID_Final),'Date.naissance']").AsCharacter();
I tried to Add this code :
Console.WriteLine(DataNaiss.ToString());
Console.ReadLine();
The output is in this picture :
Just see the end line please R.net CharacterVector . It seems that it talk about the type of DataNaiss But where are all elements of it?
In other way, until now I don't know why I have also in the same console window the data of the table DataAch imported knowing that I just call console window for showing DataNaiss and not for other thing !! you can see in the same picture elements of the first table DataAch.
my code of importing data is:
REngine engine = REngine.GetInstance();
DataFrame DataAch = engine.Evaluate("DataAch=read.table('C:/Users/isalah/Desktop/Fichiers_CRM/Fichier_csv/Achats1.csv',header=TRUE,sep =';',fill =TRUE)").AsDataFrame();
DataFrame DataDia = engine.Evaluate("DataDia=read.table('C:/Users/isalah/Desktop/Fichiers_CRM/Fichier_csv/Diagnostic.csv',header=TRUE,sep =';',fill=TRUE)").AsDataFrame();
DataFrame DataCad = engine.Evaluate("DataCad=read.table('C:/Users/isalah/Desktop/Fichiers_CRM/Fichier_csv/CADEAUX.csv',header=TRUE,sep =';',fill=TRUE)").AsDataFrame();
DataFrame DataIns = engine.Evaluate("DataIns=read.table('C:/Users/isalah/Desktop/Fichiers_CRM/Fichier_csv/Inscrits.csv',header=TRUE,sep =';',fill =TRUE)").AsDataFrame();
How do you explain this please?
Just see the end line please R.net CharacterVector . It seems that it talk about the type of DataNaiss But where are all elements of it?
Calling .ToString() on a variable won't magically show all the data you need.
According to Microsoft Documentation you can see that:
The default implementation of the ToString method returns the fully qualified name of the type of the Object
Therefor, you can understand that the type of that variable called DataNaiss in your case is actually of type CharacterVector.
Looking at the source code of R.Net you can obviously see that the class CharacterVector doesn't override ToString method.
In order to get the elements of the variable DataNaiss you have to access them yourself. The only way I can see from the source code is to access them like DataNaiss[0] since in their source code you have:
public override string this[int index]
{
get
{
if (index < 0 || Length <= index)
{
throw new ArgumentOutOfRangeException();
}
using (new ProtectedPointer(this))
{
return GetValue(index);
}
}
set
{
if (index < 0 || Length <= index)
{
throw new ArgumentOutOfRangeException();
}
using (new ProtectedPointer(this))
{
SetValue(index, value);
}
}
}
I suggest you can loop over the DataNaiss object according to it's length, and grab the data you need, for example if you have access to Length property:
for (int i=0; i<DataNaiss.Length; i++)
{
Console.WriteLine(DataNaiss[i]);
}
This is not tested. I am answering all of this according to what I read in their code.
By overriding the ToString Function on the Types in the DataNaiss variable you can print them to the Console.
Following the MSDN Guide you do can do this like this:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public override string ToString()
{
return "Person: " + Name + " " + Age;
}
}
By then calling ToString() on the objects allows you to print them.
Related
Context
I've been trying out jbEvain's powerful Mono.Cecil library for just about two weeks now. I've created the following function :
/// <summary>
/// Returns true only if they match.
/// </summary>
private bool CompareMethodDefinitionWithCodeFunction(
EnvDTE.CodeFunction pCodeFunction,
Mono.Cecil.MethodDefinition pMethodDefintion)
{
return pMethodDefintion.Name.Equals(pCodeFunction.Name)
&& pMethodDefintion.Parameters.Count == pCodeFunction.Parameters.Count;
}
Goal
The goal is to determine whether pCodeFunction and pMethodDefinition are refering to the same function definition or not. So far, I am able to compare the functions' names and the number of parameters they have. I am well aware that it's not enough to certify that they really are refering to the same function. I need help on improving my comparison. For instance, I believe one should always compare the parameter types in order to take potential function overrides into account.
Previous attempts
I have tried comparing the parameter types but none of my attempts prevailed. Allow me to demonstrate.
I thought I could compare the types as strings so I added abit of code like so :
/// <summary>
/// Returns true only if they match.
/// </summary>
private bool CompareMethodDefinitionWithCodeFunction(
EnvDTE.CodeFunction pCodeFunction,
Mono.Cecil.MethodDefinition pMethodDefintion)
{
foreach (ParameterDefinition paramDef in pMethodDefintion.Parameters)
{
Debug.WriteLine(paramDef.ParameterType.FullName);
}
foreach (CodeElement ce in pCodeFunction.Parameters)
{
CodeParameter codeParameter = ce as CodeParameter;
Debug.WriteLine(codeParameter.Type.AsFullName);
}
return pMethodDefintion.Name.Equals(pCodeFunction.Name)
&& pMethodDefintion.Parameters.Count == pCodeFunction.Parameters.Count;
}
Given that pCodeFunction was refering to the following VB.Net function at runtime
Public Function SomeFunction(ByVal arg As List(Of String)) As Object
Return New Object()
End Function
I got the following output
System.Collections.Generic.List`1<System.String>
System.Collections.Generic.List(Of System.String)
I would prefer not to mess around with these two output values and try to parse them so that they match because this doesn't seem like a very "reliable" way to compare types. What is be the most reliable way to compare the parameter types?
Bonus Notes
This function must be able to seek a function's definition so long as the source code is either VB or C#.
I am currently using the latest Mono.Cecil build (3.12.1) which you can download here
If you want to use my function and insert it in a test class that you've made, you will need the following imports :
using EnvDTE;
using Mono.Cecil;
I believe, after a few more attemps at comparing them appropriately, that there aren't any "proper" ways available out there to compare these two types of objects.
But, I have found a different solution that implies calculating a function index relative to every other function defined within the class. It can get a tiny bit complicated when we start taking the constructors defined in the IL code in consideration but I still think it's appropriate to post this answer out here since it has been my final solution so far. And to be quite frank, the solution as a whole is quite simple.
Allow me to lay out a simple class for demonstrative purposes :
class Class1
{
public static void Function1(string arg1, string arg2)
{
//business logic
}
public static Object Function2(Object arg1)
{
//business logic
}
public static void Function2(List<string> arg1)
{
//business logic
}
}
Function Index
What is my function index supposed to be? Using my Class1 example, simply put, the function's corresponding indexes would be :
0
1
2
Of course, the said function index isn't some property that comes with EnvDTE. I will have to calculate it myself. To implement it, I created a class that contains a EnvDTE.CodeFunction property as well as an int property (intended for the function index).
public class CodeFunctionWithIndex
{
public CodeFunction CodeFunction { get; set; }
public int Index { get; set; }
}
As for our Mono.Cecil.MethodDefinition's function indexes, since we are looping on them (see main post), we can easily calculate their indexes.
It doesn't simply end here though! There are a few things that I need to mention if you want to use the same approach.
To my limited understanding of what goes on behind Mono.Cecil's convenient library, the list of MethodDefinition we are looping through contains all the functions that were generated in IL code after our dll was compiled. But, the class from which our EnvDTE.CodeFunctions reside isn't compiled.
Does a Mono.Cecil.Type (AKA class) contain as many functions as a EnvDTE.ProjectItem (refering to the class)?
No!
Here is what we will have to consider : the constructor(s). A class may or may not have explicitly defined constuctors. But, a Mono.Cecil.Type (AKA the class object of Mono.Cecil) must contain at least one constructor. And believe me, if you don't explicitly define your own constructor, there will be one in the Mono.Cecil.Type!
Finding out if a constructor is explicitly defined within our EnvDTE.ProjectItem(refering to the class) isn't such a hard task. Well... unless you consider the following code complicated.
private List<CodeFunctionWithIndex> GetExplicitlyDefinedConstructors(vsCMElement pRequestedCodeElementKind, CodeElements pCodeElements)
{
int nbCodeFunction = 0; //calculated function index
List<CodeFunctionWithIndex> constructorList = new List<CodeFunctionWithIndex>();
if (pCodeElements != null)
{
foreach (CodeElement element in pCodeElements)
{
//if current element is a namespace
if (element.Kind == vsCMElement.vsCMElementNamespace)
{
constructorList = GetExplicitlyDefinedConstructors(pRequestedCodeElementKind, ((EnvDTE.CodeNamespace)element).Members);
if (!constructorList.Any())
continue;
return constructorList;
}
//if current element is a class
else if (element.Kind == vsCMElement.vsCMElementClass)
{
nbCodeFunction = 0;
constructorList = GetExplicitlyDefinedConstructors(pRequestedCodeElementKind, ((EnvDTE.CodeClass)element).Members);
if (!constructorList.Any()) //because there might be more than one class defined within the active file
continue;
return constructorList;
}
//if current element's kind equals the requested kind
else if (element.Kind == pRequestedCodeElementKind)
{
nbCodeFunction++;
//if it's a constructor, add its index to the list of constructor indexes
if (((CodeFunction)element).FunctionKind.ToString().Contains(vsCMFunction.vsCMFunctionConstructor.ToString()))
{
constructorList.Add(
new CodeFunctionWithIndex()
{
CodeFunction = ((CodeFunction)element),
Index = nbCodeFunction
});
}
}
}
}
return constructorList;
}
And here is how I am calling this function to find out if I have any explicitly defined constructors :
GetExplicitlyDefinedConstructors(
vsCMElement.vsCMElementFunction,
DTE.ActiveDocument.ProjectItem.FileCodeModel.CodeElements)
.Any();
But, if there aren't any constructors defined in it, how can our Mono.Cecil.MethodDefinition's function index match with our EnvDTE.CodeFunction's function index?.
Here is the big idea of my solution (tested) :
In VB.Net, if there is no explicitly defined constructor within the class, the constructor in the IL code will be situated at the beguining of the class (function index 0).
In C#.Net, if there is no explicitly defined constructor within the class, the constructor in the IL code will be situated at the end of the class (last function index).
Here is what my function CompareMethodDefinitionWithCodeFunction proposed in my first post looks like today (yes it's been renamed... I apologize for that):
public MethodDefinition FindMethodDefinition(CodeFunctionWithIndex pCodeFunction, bool pHasAnExplicitlyDefinedCtor)
{
//Get the assembly that should contain the function we seek
//Note : this is done by comparing pCodeFunction's assembly name to every assembly's name (without the extension)
ModuleDefinition assemblyContainingMethod = assemblies
.Where(assem =>
assem.Name.Split(new char[] { '.' }).FirstOrDefault()
.Equals(pCodeFunction.CodeFunction.ProjectItem.ContainingProject.Properties.Item("AssemblyName").Value, StringComparison.CurrentCultureIgnoreCase))
.FirstOrDefault();
//Get the class that should contain the function we seek
//Note : pCodeFunction.Parent.Name is the class name of our pCodeFunction
TypeDefinition classContainingMethod =
assemblyContainingMethod.Types
.Where(cl => cl.Name.Equals(((CodeClass)pCodeFunction.CodeFunction.Parent).Name))
.FirstOrDefault();
//below is what you want to see
bool isCtorAtIndexZero = DTE.ActiveDocument.ProjectItem.Name.EndsWith(".vb");
int functionIndex = 0;
for (int i = 0; i < classContainingMethod.Methods.Count; i++)
{
if (!pHasAnExplicitlyDefinedCtor && isCtorAtIndexZero && i == 0)
continue;
if (functionIndex == pCodeFunction.Index)
return classContainingMethod.Methods[i];
functionIndex++;
}
return null;
}
This code is extracted from a working project.
The assemblies variable is a class property of type List<ModuleDefinition>. By the time this function is called, it will contain the assembly in which the function we seek can be found.
Bear with me as I can only clarify so much. The project is rather big, in my opinion anyways, and it can perform many operations that I need to omit from this post as it is not directly related to the question in the first place.
Hope this helps at least a tiny bit. I apologize for the wall of text.
Input string was not in correct form.
I'm getting an exception on runtime as "System.FormatException".
Follwing lines shows exception-
public int Task
{
get
{
return Int32.Parse(TaskText.Text);
}
set
{
TaskText.Text = value.ToString();
}
}
public int Project
{
get
{
return Int32.Parse(ProjectText.Text);
}
set
{
ProjectText.Text = value.ToString();
}
}
I also tried -
Convert.ToInt32(TaskText.Text)
Convert.ToInt32(ProjectText.Text)
I need to pass these to following constructor,
Harvest_TimeSheetEntry entry = new Harvest_TimeSheetEntry(client,starttime,stoptime,task,project);
this constructor is stored in some class with task and project as integer parameters. And I can't change it because if i changed, it affects other code.
It looks as though you're getting your input from controls accepting user input, which is just asking for failure, since a user can potentially enter something that doesn't represent an integer value. You can use TryParse to avoid this:
var result = 0;
if (int.TryParse(TaskText.Text, out result)) {
return result;
}
return 0;
So, if the value of TaskText.Text == "1", this will succeed; if the value of TaskText.Text == "aaaa", this will fail - and return zero. You example would raise the appropriate exception, as experienced.
However, an exception might be the right thing to happen here, if you can't handle a bad value, don't have an alternative, and the application relies on the input to move forward. More likely, you could do with some validation on your input fields to prevent bad data being submitted.
Since your Harvest_TimeSheetEntry constructor expects task and project to be integers, you must have a list of integers that correspond to the different tasks and projects. Now you can't expect Int32 to know which task corresponds to which number, can you?
I would suggest you use ComboBoxes for TaskText and ProjectText. Then, you can assign the correct corresponding integer to each ComboBoxItem.Tag.
Please note that this goes far beyond the kind of answers you should expect from SO.
if you do not use MVVM or binding you can simply do the check before your need it. t
int task;
int project;
if(!Int32.TryParse(TaskText.Text, out task))
{} //errorhandling here
if(!Int32.TryParse(ProjectText.Text, out project))
{}//errorhandling here
//all fine
var entry = new Harvest_TimeSheetEntry(client,starttime,stoptime,task,project);
You must check if you can parse it into Integer
try
Int32 foo =0;
if (Int32.TryParse(TaskText.Text, out foo))
{
return foo;
}
My question is sort of like the one found here:
How do I name variables dynamically in C#?
However its a bit different so I'm wondering if its possible.
I'm trying to read in a bunch of strings from a .settings file.
I have them all named Time1, Time2,Time3 etc...
I want the User to be able to add more Times to the file so there could be Time100 or more.
I have a Size in the settings file that will keep track of the amount of Time Variables.
I want to write something that will read in all of the Time strings. I think it would be silly to pre-fill the .settings file with 100 Time Variables so I know they are there and then manually read in each one.
So I'm wondering if there is a way where I can read in Timei or Time+i where I is an integer that I can put in a loop that will find them all.
(note that the data is string not time, its just going to be converted to days of the week)
Such as: (Days is from ApplicationSettingsBase [aka file add new Settings1.settings]
public static int AvDaysIndex = Days.Default.Size; //This holds the number of items in Days
public static DayOfWeek[] AvailableDays = new DayOfWeek[AvDaysIndex]; //This is where I wants to read in all the variables Aka Time1 Time2 Times3
public ReadInDays() //Reads in from the .settings File
{
if(AvDaysIndex>0) // Makes sure there is something in Days to read
{
int I=0;
//I can Manually do the following
AvailableDays[I++] = Days.Default.Time1;
AvailableDays[I++] = Days.Default.Time2;
AvailableDays[I++] = Days.Default.Time3; //etc...
//Is there a way to do something like this
for (int i = 0; i < AvDaysIndex; i++) //reads in each time
{
AvailableDays[i] = Days.Default.Time +i;//where I would be added to the variable name to find it?
//Or something like
AvailableDays[i] = Days.Default.Time(I.tostring())
}
}
}
Hopefully all that at least makes it clear what I'm trying to do.
Edit - I'm starting to think my issue is actually with the .settings file. and that if I just read values in from another file type where the values don't have names I can easily read them in even though there is a variable number of elements in the file.
Solution -
for (int i = 0; i < Index; i++)
{
AvailableDays[i] = getFromFile(_Days.Default.Properties["Time" + (i+1).ToString()].DefaultValue.ToString());
AvailableTimes[i] = Convert.ToDateTime(_Times.Default.Properties["Time" + (i + 1).ToString()].DefaultValue);
}
It was all in figuring out how to read in from the .settings file and instead of reading it in directly aka Days.Default.Time1; I had to to do a generic lookup from Days.Default.Properties and then I could create a dynamic name and find it. You guys probably were trying to tell me how to do this, I just didn't understand.
Thanks again to all those that helped.
I would use a hashtable/dictionary to store the Days.Default.TimeX variations
hashtable["Time1"]...hashtable["TimeN"]
As already mentioned a hashtable or a dictionary would probably serve you best. If you go the dictionary route you can create a string/int indexer on the class and you would be able to alter your code slightly:
http://msdn.microsoft.com/en-us/library/2549tw02%28v=vs.80%29.aspx - Example of creating indexer on a class:
Example Indexer Class:
public class Default
{
private Dictionary<int, DayOfWeek> _values = new Dictionary<int,DayOfWeek>();
public DayOfWeek this[int index]
{
get
{
if (_values.ContainsKey(index))
return _values[index];
else
return null;
}
set
{
_values[index] = value;
}
}
}
Original:
AvailableDays[i] = Days.Default.Time(I.tostring())
Would become:
AvailableDays[i] = Days.Default.Time[I];
Reflection is always an option too and i have an example below that is in a Windows Console Application:
public class Default
{
public int Time1 { get; set; }
public int Time2 { get; set; }
public int Time3 { get; set; }
}
class Program
{
static void Main(string[] args)
{
Default d = new Default();
Type t = d.GetType();
foreach (var info in t.GetProperties())
{
//SET VALUE
info.SetValue(d, 1);
}
foreach (var info in t.GetProperties())
{
//GET VALUE
Console.WriteLine("Property: {0}", info.Name);
Console.WriteLine("Value: {0}", info.GetValue(d));
}
//OR JUST ONE PROPERTY
Console.WriteLine("Time1 Property Value: {0}", t.GetProperty("Time1").GetValue(d));
Console.ReadLine();//PAUSE THE CONSOLE AFTER PROCESSING
}
}
In your example using reflection:
Days.Default.GetType().GetProperty("Time" + I.ToString()).GetValue(Days.Default) as DayOfWeek;
Another option could be to use Reflection. And getting the values from the enum on the fly.
See the link: How to Get Enum Values with Reflection in C#
However, using a Dictionary<string, DayOfWeek> will give you better performance and more readable code.
I think you could better resolve your problem by implementing your configuration using a
ConfigurationElementCollection. Then the 'names' of the configuration elements are irrelevant. You enumerate a collection of values and use those directly.
See here for an example; How to implement a ConfigurationSection with a ConfigurationElementCollection.
I have an MS Dynamics AX 2012 project and I am using .Net interop.
There is a C# method inside a static class called Database:
public static List<String> GetAllDatabases(string dataSource)
After referencing this assembly, I can execute in X++:
ADOMD.ADOMD.Model.Database::GetAllDatabases();
But I can't read the string list that it's returning.
I would like to use something like:
List databaNameCollection = new List( Types::String );
;
databaNameCollection = ADOMD.ADOMD.Model.Database::GetAllDatabases();
But it trows an error:
Error executing code: (object) has no valid runable code in method 'GetSID'.
How could I do it?
-------EDITED------
I found this post:
http://blogs.msdn.com/b/x/archive/2010/01/19/traversing-elements-in-an-ienumerable-from-x.aspx
But it was in 2010, probably for AX 2009, I tried to assign:
ClrObject enumerator;
str theValue;
;
enumerator = ADOMD.ADOMD.Model.Database::GetAllDatabases();
while (enumerator.MoveNext())
{
theValue = enumerator.get_Current();
print theValue;
}
The GetallDatabases method is working with another .Net project, it is returning 10 objects, but at the X++ code, is returning nothing.
Thanks
To answer your question about .NET types in X++ and get_{x} and set_{x}:
.NET properties are shown in X++ as methods. For example, the get & set property below in C#
string Name {get;set;}
will show in X++ as
string get_Name();
void set_Name(str value);
Basically C# properties are just syntactic sugar. The C# compiler will create a get_{x} method for each get property and a set_{x} for each set property.
In your case, if you want to access the Name property in the cubeDef object you would have to write something like this in X++:
info(cubeDef.get_Name());
I made it using the example at: http://blogs.msdn.com/b/x/archive/2010/01/19/traversing-elements-in-an-ienumerable-from-x.aspx
But without the enumerator.MoveNext(), since it is not an X++ Object, changing it to a for loop worked, the final code is:
ClrObject enumerator;
str theValue;
int i;
int length = 0;
List databaNameCollection = new List( Types::String );
;
try
{
permission = new InteropPermission(InteropKind::CLRInterop);
if (permission == null)
{
return;
}
permission.assert();
enumerator = ADOMD.ADOMD.Model.Database::GetAllDatabases();
length = enumerator.get_Count();
for (i = 0; i < length; i++)
{
stringElement = enumerator.get_Item(i);
databaNameCollection.addStart(stringElement);
}
CodeAccessPermission::revertAssert();
}
catch (Exception::CLRError)
{
CodeAccessPermission::revertAssert();
info(CLRInterop::getLastException().ToString());
}
But some questions still remain:
1) I can't assign databaNameCollection.addStart(enumerator.get_Item(i)); directly.
2) I can't access the complex objects attributes, like:
cubeDef = enumerator.get_Item(i);
info(cubeDef.Name);
where cubeDef is of type: Microsoft.AnalysisServices.AdomdClient.CubeDef.
3) I can't find the documentation of the CLRObject that describes these get_{propertyName} methods.
EX: get_Item
Best Regards
So I'm playing around with EnvDTE, and the EnvDTE.CodeModel API, And I was wondering if there was a way to get the text value represented by a CodeElement.
Let's say I have an CodeAttribute, is there some way to get a string of what the CodeAttribute represents, i.e.[MyAttribute(value="myvalue")].
I know it's possible to reconstruct the code using the various properties of the CodeElement, at least in some scenarios, but for some things it seems it would be easier to just get the text.
Thanks!
The CodeElement interface has the properties StartPoint and EndPoint which represent the start and end of the element within the buffer. These contain the Line Number / Column which can be passed to methods like IVsTextLines.GetLineText and give you back the value you're looking for.
To get the IVsTextLines for a given CodeElement you can do the following
CodeElement ce = ...;
TextDocument td = ce.StartPoint.Parent;
IVsTextLines lines = td as IVsTextLines;
void WriteMapping(CodeProperty codeProperty)
{
WriteLine("");
WriteLine("///CodeProperty");
WriteLine("///<summary>");
WriteLine("///"+codeProperty.FullName);
WriteLine("///</summary>");
if(codeProperty.Getter==null && codeProperty.Setter==null)
return;
if(codeProperty.Attributes!=null){
foreach(CodeAttribute a in codeProperty.Attributes)
{
Write("["+a.FullName);
if(a.Children!=null && a.Children.Count>0)
{
var start=a.Children.Cast<CodeElement>().First().GetStartPoint();
var finish= a.GetEndPoint();
string allArguments=start.CreateEditPoint().GetText(finish);
Write("("+allArguments);
}
WriteLine("]");
}
}
Write("public "+GetFullName(codeProperty.Type) +" "+codeProperty.Prototype);
Write(" {");
//if(codeProperty.Getter!=null && codeProperty.Getter.Access!=vsCMAccess.vsCMAccessPrivate)
Write("get;");
//if(codeProperty.Setter!=null)
Write("set;");
WriteLine("}");
}
In addition to the answer by #JaredPar, an alternative approach would be:
public string GetText(CodeAttribute attribute)
{
return attribute.StartPoint.CreateEditPoint().GetText(attribute.EndPoint);
}
That's it!! (Thanks #JaredPar for the pointers)
Source: http://msdn.microsoft.com/en-us/library/envdte.editpoint.gettext.aspx