I'm still quite new to C#, I know this is pretty easy in VBA (my "preferred" language). I have a bunch of data input objects (text/numbers/dates) and I want to be able to validate that the input is logical for the field. I don't want dates entered where text should be, I don't want integers entered where dates should be, etc...
I found this code that checks to see if a date entered is a valid date. However, I'm confused as to where in a C#/.NET app this function should go, and I'm confused as to how to call the function from one of my pages. Any help is appreciated. At the moment I have it in Site.Master.cs, which sounded like the proper place to be. I should state that I'd like to be able to put this validation in one place, as opposed to putting it on every form, because I've got 10 forms that have data entry controls on them.
static bool IsValidSqlDateTimeNative(string someval)
{
bool valid = false;
DateTime testDate = DateTime.MinValue;
System.Data.SqlTypes.SqlDateTime sdt;
if (DateTime.TryParse(someval, out testDate))
{
try
{
// take advantage of the native conversion
sdt = new System.Data.SqlTypes.SqlDateTime(testDate);
valid = true;
}
catch (System.Data.SqlTypes.SqlTypeException ex)
{
// no need to do anything, this is the expected out of range error
}
}
return valid;
}
Why don't you add a new class and have this as a static method so you can call it from anywhere in your application?
For example:
public static class DateTimeHelpers
{
static bool IsValidSqlDateTimeNative(string someval)
{
bool valid = false;
DateTime testDate = DateTime.MinValue;
System.Data.SqlTypes.SqlDateTime sdt;
if (DateTime.TryParse(someval, out testDate))
{
try
{
// take advantage of the native conversion
sdt = new System.Data.SqlTypes.SqlDateTime(testDate);
valid = true;
}
catch (System.Data.SqlTypes.SqlTypeException ex)
{
// no need to do anything, this is the expected out of range error
}
}
return valid;
}
}
Then call from anywhere in the application like this:
bool result = DateTimeHelpers.IsValidSqlDateTimeNative(mystring);
public static class Validation
{
public static bool IsValidSqlDateTimeNative(string someval)
{
DateTime testDate;
return DateTime.TryParse(someval, out testDate) &&
testDate >= SqlDateTime.MinValue.Value;
}
}
Usage:
var isValidSqlDate = Validation.IsValidSqlDateTimeNative("1200-01-01");
Also worth mentioning is that you can use datatype DateTime2 in the database which has a larger date range (same as the .net DateTime type) and a larger fractional precision.
A big difference between creating web-pages in .NET versus most scripting languages is that everything is generally compiled together into one big (fat) binary. This is generally the equivalent of having a single include.<lang> that includes everything, and then include that into your page. What this means in practice, is that you in C#/.NET normally create classes that are .cs files (ie. not in pages/master-files), and you simply call the functions/classes defined in said files from your pages/masters-files.
Also, as of C#'s object-oriented structure, you can't just create functions in the global namespace (or any namespace for that matter), you have to create a class, and then have your function live inside said class.
Related
Now, ive bumped into so many different responses to the usage of Date in C#
Ranging from using:
DateTime.Parse
Date.Now
etc. There seems to me a huge amount of ways to use the time date funtion. What i need to do is Read the Day, Month and Year from say today (assuming Date.Now?) and store these values individually so that they can be referenced throughout the entire budget.
The way i was looking at doing this was by having the DateTimeStorage Class in its own Classes Folder. That way, i can reference it at any point throughout the entire project right?
The issue i have bumped into is that i get an error immediately with the following two lines within the class:
class DateTimeStorage
{
String stringDate;
DateTime dateValue = DateTime.Parse(stringDate);
}
According to this, stringDate has an error
a field initialiser cannot reference the non-static field
Now, i was going to close the Class by storing the string values like below:
class DateTimeStorage
{
String stringDate;
DateTime dateValue = DateTime.Parse(stringDate);
String day = datevalue.Day.ToString();
//etc
}
This doesnt work either, "dateValue does not exist in the current context"
Now, im completely stumped and not sure how best to approach this. There are so many different ways ive seen to do dates. Its hard to know if any of them work the way i need them to.
Would anyone have any suggestions? I need to store the variables as strings as they are going to be used through the entire project to populate fields etc.
Any help would be hugely appreciated
What about a static class to store the current date. You could modify this such that the date is able to be updated from elsewhere in the code but this is the simplest approach that initializes the date to Now on program start up.
using System;
namespace ClassLibrary3
{
public static class StaticDate
{
static StaticDate()
{
//Initialize Date
var date = DateTime.Now;
Year = date.Year;
Month = date.Month;
Day = date.Day;
}
public static readonly int Year;
public static readonly int Month;
public static readonly int Day;
}
public class SomeOtherClass
{
public void MethodThatNeedsDate()
{
var year = StaticDate.Year;
var day = StaticDate.Day;
}
}
}
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.
I am using DateTime and it's methods like DateTime.AddMinutes etc.
Is there a way to make DateTime throw an Exception when adding a negative number of minutes/seconds etc that make the time fall beneath 00:00 and not turn the time to 23:59?
At Domain Model Level
At the domain model you could a Decorator/Wrapper class. Just use a class that has a private DateTime object and pass through every method of that object that remains unaltered and implement those that are altered, essentially just by writing:
public bool Equals(DateTime dt){
return this.dateTime.Equals(DateTime dt);
}
There are however a couple of issues with this:
In the above example you might want to compare your DateTime object with itself, but that won't be possible.
DateTime has certain attributes eg. its serializable that you may lose until adding a fair bit of time to this.
At Controller Level
Assuming you are implementing this in an applicatino with MVC setup, you probably have some validation within your controller. That should be able to handle these cases.
I'd recommend this approach, as you can reject any case where the Date part of the datetime does not match or is less than the original date.
You can try a extension method like so:
public static class MyDateTimeChecker
{
public static bool CheckTime(this DateTime dt, int minutes)
{
if (dt.Day > dt.AddMinutes(minutes).Day)
return false;
else
return true;
}
}
I placed Day since in your question you wanted to know if it would fall bellow 00:00 or back to the previous day at 23:59,so this is one way to go.
Then in your code you can use it like this:
DateTime dt = DateTime.Now;
if(dt.CheckTime(-1440))
{
//if true your negative number was in range
//so use it if you like.
}
else
}
//oops too much
}
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;
}
I'm having some issues with System.Reflection in C#. I'm pulling data from a database and retrieving that data in a JSON string. I've made my own implementation of handling the data from JSON into my self declared objects using Reflection. However, since I ussually get a JSON string with an array of like 50 - 100 objects my program runs really slow because of the loops I'm using with reflection.
I've heard that reflection is slow but it shouldn't be this slow. I feel something is not right in my implementation since I have a different project where I use JSON.NET serializer and instantiate my objects a bit differently with reflection that runs just fine on the same output (less than a second) while my slow program takes about 10 seconds for 50 objects.
Below are my classses that I'm using to store data
class DC_Host
{
public string name;
public void printProperties()
{
//Prints all properties of a class usign reflection
//Doesn't really matter, since I'm not usign this for processing
}
}
class Host : DC_Host
{
public string asset_tag;
public string assigned;
public string assigned_to;
public string attributes;
public bool? can_print;
public string category;
public bool? cd_rom;
public int? cd_speed;
public string change_control;
public string chassis_type;
//And some more properties (around 70 - 80 fields in total)
Below you'll find my methods for processing the information into the objects that are stored inside a List. The JSON data is stored inside a dictionairy that contains a another dictionairy for every array object defined in the JSON input. Deserialising the JSON happens in a matter of miliseconds so there shouldn't be a problem in there.
public List<DC_Host> readJSONTtoHost(ref Dictionary<string, dynamic> json)
{
bool array = isContainer();
List<DC_Host> hosts = new List<DC_Host>();
//Do different processing on objects depending on table type (array/single)
if (array)
{
foreach (Dictionary<string, dynamic> obj in json[json.First().Key])
{
hosts.Add(reflectToObject(obj));
}
}
else
{
hosts.Add(reflectToObject(json[json.First().Key]));
}
return hosts;
}
private DC_Host reflectToObject(Dictionary<string,dynamic> obj)
{
Host h = new Host();
FieldInfo[] fields = h.GetType().GetFields();
foreach (FieldInfo f in fields)
{
Object value = null;
/* IF there are values that are not in the dictionairy or where wrong conversion is
* utilised the values will not be processed and therefore not inserted into the
* host object or just ignored. On a later stage I might post specific error messages
* in the Catch module. */
/* TODO : Optimize and find out why this is soo slow */
try
{
value = obj[convTable[f.Name]];
}
catch { }
if (value == null)
{
f.SetValue(h, null);
continue;
}
// Het systeem werkt met list containers, MAAAR dan mogen er geen losse values zijn dus dit hangt
// zeer sterk af van de implementatie van Service Now.
if (f.FieldType == typeof(List<int?>)) //Arrays voor strings,ints en bools dus nog definieren
{
int count = obj[convTable[f.Name]].Count;
List<int?> temp = new List<int?>();
for (int i = 0; i < count; i++)
{
temp.Add(obj[convTable[f.Name]][i]);
f.SetValue(h, temp);
}
}
else if (f.FieldType == typeof(int?))
f.SetValue(h, int.Parse((string)value));
else if (f.FieldType == typeof(bool?))
f.SetValue(h, bool.Parse((string)value));
else
f.SetValue(h, (string)value);
}
Console.WriteLine("Processed " + h.name);
return h;
}
I'm not sure what JSON.NET's implementation is in the background for using reflection but I'm assumign they use something I'm missing for optimising their reflection.
Basically, high-performance code like this tends to use meta-programming extensively; lots of ILGenerator etc (or Expression / CodeDom if you find that scary). PetaPoco showed a similar example earlier today: prevent DynamicMethod VerificationException - operation could destabilize the runtime
You could also look at the code other serialization engines, such as protobuf-net, which has crazy amounts of meta-programming.
If you don't want to go quite that far, you could look at FastMember, which handles the crazy stuff for you, so you just have to worry about object/member-name/value.
For people that are running into this article I'll post my solution to my problem in here.
The issue wasn't really related to reflection. There are ways to improve the speed using Reflection like CodesInChaos and Marc Gravell mentioned where Marc even craeted a very usefull library (FastMember) for people with not too much experience in low level reflection.
The solution however was non related to reflection itself. I had a Try Catch statement to evaluate if values exist in my dictionary. Using try catch statements to handle program flow is not a good idea. Handling exceptions is heavy on performance and especially when you're running the debugger, Try Catch statements can drastically kill your performance.
//New implementation, use TryGetValue from Dictionary to check for excising values.
dynamic value = null;
obj.TryGetValue(convTable[f.Name], out value);
My program runs perfectly fine now since I omitted the TryCatch statement.