|
It's obvious the code shown here depends on a context which you don't show; a guess would be that this code is being used with a 3rd. party Control:
1. there's no override named 'Validate for either a WinForm, or a sub-classed TextBox.
2. you never do anything with the Control passed as a parameter.
3. the string assignments to 'ErrorText use (probably) a Property in the context here; a guess would be that the 'setter of that Property has "side-effects."
4. the 'Value parameter here comes in as an Object, but clearly it is a string.
If I thought the user entering text here was going to type in an integer most of the time:
Int32 _minValue = 0;
Int32 _maxValue = 100;
Int32 trialvalue;
private bool checkInt(object val)
{
string strval = val.ToString();
if (Int32.TryParse(strval, out trialvalue))
{
if (trialvalue >= _minValue && trialvalue <= _maxValue) return true;
return false;
}
return false;
} Comments:
1. measuring the "complexity" of this code is probably useless since (guess) its structure is dictated by the whatever you over-ride, and depends on that for error-reporting.
2. I'd certainly want to get the string creation used for the error messages here outside of the method; some of them can be declared string constants.
«I want to stay as close to the edge as I can without going over. Out on the edge you see all kinds of things you can't see from the center» Kurt Vonnegut.
|
|
|
|
|
Thank you,
Yes you are right, it was inherited from a third party control, but the parameter Control will be handled by the base class, and the ErrorText is also a property.
basically the type of the parameter Value will defend on how it was implemented. but in this case, while the input will came from a user using either a textbox or other winform controls. so it was a string then will be validated if it is a integer.
here is my solution
public override bool Validate(Control control, object value)
{
if (value == null && !_IsAllowNull)
{
ErrorText = "Please provided valid number without a decimal point.";
return false;
}
if (value.ToString().Contains("."))
{
ErrorText = "Decimal value is not allowed";
return false;
}
if (!value.IsNumber())
{
ErrorText = "Please provided valid number without a decimal point.";
return false;
}
if (value.ToInt() < _minValue || value.ToInt() > _maxValue)
{
ErrorText = "Value should not be greater than " + _maxValue + " or less than " + _minValue;
return false;
}
return true;
}
the complexity of this solution just drop 3 point.
but I like your solution, I will try to implement it.
once again, thank you.
|
|
|
|
|
I'm glad you found some value in my response.
While predicting the frequency of "correct" values entered by a user, or coming from some "other Control or code," is always dicey, I think it's often worth it.
I can't know, looking at your code, if it's always the case that if the 'value parameter is an Int32 then the Control parameter will be null.
If there is some variation in what you get in the Control parameter, you might be able to exploit that to simplify your code.
If you think the Type of the 'value parameter is going to be Type Int32 more frequently than Type String, or some other Type:
if (value is Int32)
{
int valasInt32 = Convert.ToInt32(val);
return ?
}
if (value is string)
{
return ?
}
Ideally, you could use the suggestion by Chris Quinn on this thread to create an input Control that never let you enter any character that was not an integer. Does the 3rd. party Control you use (DevXpress ?) provide any Keyboard hooks you could exploit ?
«I want to stay as close to the edge as I can without going over. Out on the edge you see all kinds of things you can't see from the center» Kurt Vonnegut.
modified 6-Nov-15 8:39am.
|
|
|
|
|
Yes it was a from Devexpres, actually i was implementing the ValidationRule from DevExpress.XtraEditors.DXErrorProvider then use it with dxValidationProvider
here the code that will validate an int
public sealed class ValidateInteger : ValidationRule
{
private int _maxValue = int.MaxValue;
private int _minValue = int.MinValue;
private bool _IsAllowNull;
public ValidateInteger(bool isAllowNull = false)
{
_IsAllowNull = isAllowNull;
}
public ValidateInteger(int min, int max, bool isAllowNull = false)
{
_maxValue = max;
_minValue = min;
_IsAllowNull = isAllowNull;
}
public override bool Validate(Control control, object value)
{
if (value == null && !_IsAllowNull)
{
ErrorText = "Please provided valid number without a decimal point.";
return false;
}
if (value.ToString().Contains("."))
{
ErrorText = "Decimal value is not allowed";
return false;
}
if (!value.IsNumber())
{
ErrorText = "Please provided valid number without a decimal point.";
return false;
}
if (value.ToInt() < _minValue || value.ToInt() > _maxValue)
{
ErrorText = "Value should not be greater than " + _maxValue + " or less than " + _minValue;
return false;
}
return true;
}
}
then use it like this
dxValidationProviderMain.SetValidationRule(txt_height, new Validators.ValidateInteger(false));
then call
dxValidationProviderMain.Validate()
|
|
|
|
|
I don't use DevXpress, but any time I see a 'sealed Class, I'd wonder how I could modify it, since I can't sub-class it.
«I want to stay as close to the edge as I can without going over. Out on the edge you see all kinds of things you can't see from the center» Kurt Vonnegut.
|
|
|
|
|
Yes, it was intentional sealed, i don't see any chances that it will be become a base class someday, but if it will then we can just remove the sealed keyword. I just don't know if it is a good practice.
|
|
|
|
|
Well, yes, if you have the source, you could "un-seal" the class ... but ...
I suggest you consider the idea that you may be pursuing "micro-optimization" here, and that may have very little pay-off.
You might enjoy reading Eric Lippert's thoughts on micro-optimization in .NET: [^]
«I want to stay as close to the edge as I can without going over. Out on the edge you see all kinds of things you can't see from the center» Kurt Vonnegut.
|
|
|
|
|
Bookmark
I will gonna read it later.
Thanks
|
|
|
|
|
There are a few things you can do. BillWoodRuff gave a good example.
- the control variable is never used inside the function.
- Is there a reason to pass value as an object? In addition I would never use a keyword (value) as a variable name. (unless the autofill gave it that name of course)
- I never program multiple exit points in a function, often it is harder to debug. Better to set a boolean and return that at the end. (although that's more a matter of taste)
- Keep the { }. It will be easier to add a statement if a modification is needed.
- int.TryParse is a very good function. I also often use Convert.ToInt32, but make sure you know what it returns in case of null values or invalid integer strings/objects. (read MSDN doc)
- In some countries the decimal sign is not a ".", but a komma ",".
- You don't need _minValue or _maxValue you have int.MinValue and int.MaxValue.
- An object variable has an IsNumber() and ToInt() function? (not in version 4.5)
Hope this helps.
|
|
|
|
|
hmm about the decimal sign, its new to me that it is a comma to other country.
BTW, basically the initial value of _minValue and _maxValue is from the int.MinValue and int.MaxValue, but in some point it could be possible that i will limit the value the user can entered, and it was defined in the constructor.
private int _maxValue = int.MaxValue;
private int _minValue = int.MinValue;
private bool _IsAllowNull;
public ValidateInteger(bool isAlloweNull = true)
{
_IsAllowNull = isAlloweNull;
}
public ValidateInteger(int min, int max, bool isAlloweNull = false)
{
_maxValue = max;
_minValue = min;
_IsAllowNull = isAlloweNull;
}
while the IsNumber() and ToInt() is a custom extension.
Thank you
|
|
|
|
|
Personally I would put a mask on the control to only allow the entering of digits 0-9, then all you have to check is that the entry is not outside the max and min values.
=========================================================
I'm an optoholic - my glass is always half full of vodka.
=========================================================
|
|
|
|
|
Yes I can do this. but i can easily miss it.
thanks
|
|
|
|
|
I'd say it's not too bad. Drop all the elses, they are not needed as each condition returns out. That will remove some of the indentation.
If value is null and nulls are allowed, then it'll throw a null exception on the ToString(). The error message for the null check is wrong.
The IsNumber() and ToInt() functions are interesting, as in they don't exist on object. Extension methods? The assumption seems to be that the number is actually a string representation of a number, in which case first confirm it is a string, then do a int.TryParse to extract it...
Regards,
Rob Philpott.
|
|
|
|
|
yup the IsNumber() and ToInt() is a custom extension, basically the IsNumber() will identify the string if it can be a number(either a decimal,int and so on), while the ToInt() as you expected will convert a value to int.
BTW thank you, for your suggestion
|
|
|
|
|
A question on QA [^] from someone who knows the internal structure of a Type, but does not have a reference to the Type or an Interface the Type implements ... and who needs to cast the Type as Object to its original Type to access its internal field.
In other words: I have an instance of this Class cast to Object:
public class ExampleClass
{
public int ExId { set; get; }
public string ExString { set; get; }
public ExampleClass(int exId, string exString)
{
ExId = exId;
ExString = exString;
}
} And, my code does not contain the definition of this Class.
So I want to cast the instance of ExampleClass as Object to its Native Type. The thought occurred to me that it might be possible, since I know the internal structure of ExampleClass to "spoof" an Interface like this:
public interface IExample
{
int ExId { set; get; }
string ExString { set; get; }
} And, use it like this on the instance to get it back to ExampleClass Type:
IExample iexample = example as IExample;
This results in the value of 'iexample being set to 'null.
I also tried "spoofing" the Class, and using that:
public class xExample
{
public int ExId { set; get; }
public string ExString { set; get; }
public xExample(int exId, string exString)
{
ExId = exId;
ExString = exString;
}
}
xExample xexample = ExampleClassAsObject as (xExample); My conclusion is that this kind of "spoofing" is not possible in .NET, and, being foolish enough to ask why, I ask: why ? Security reasons ? A "spoof" is never "the real thing" ?
Just curious, thanks.
«I want to stay as close to the edge as I can without going over. Out on the edge you see all kinds of things you can't see from the center» Kurt Vonnegut.
|
|
|
|
|
Try it with the dynamic keyword;
using System;
class ConsoleApplication
{
public class ExampleClass
{
public int ExId { set; get; }
public string ExString { set; get; }
public ExampleClass(int exId, string exString)
{
ExId = exId;
ExString = exString;
}
}
static void Main(string[] args)
{
object ec = new ExampleClass(1, "hello world");
dynamic ec2 = ec;
Console.WriteLine(ec2.ExString);
Console.ReadLine();
}
}
BillWoodruff wrote: Security reasons ? I think it is a technical "feature", a side-effect. Otherwise, dynamic would be a nice hole in that security.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Thanks, Eddy, that's a use of 'dynamic I never would have thought of.
«I want to stay as close to the edge as I can without going over. Out on the edge you see all kinds of things you can't see from the center» Kurt Vonnegut.
|
|
|
|
|
Your welcome ofc
I'd see it more as a bit of abuse; it is not a very nice 'solution', but it does the trick. Will explode as soon as someone changes the name of the property. Not during compile time, but during runtime. A compile-time check would be preferred.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
The answer, as always, lies in the il. Specifically, you're looking at these two lines:
L_001a: ldfld class SpoofTest.ExampleClass SpoofTest.Class1::example
L_001f: isinst SpoofTest.IExample So, the code loads the instance and then tests it to see if it's an instance of your interface. Obviously, it's not an instance so the code would leave iexample as nulL, so this code
public Class1()
{
IExample iexample = example as IExample;
if (iexample == null)
{
System.Diagnostics.Debug.WriteLine("This does not compute");
}
} produces this IL
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 3
.locals init (
[0] class SpoofTest.IExample iexample,
[1] bool CS$4$0000)
L_0000: ldarg.0
L_0001: ldc.i4.1
L_0002: ldstr "Test"
L_0007: newobj instance void SpoofTest.ExampleClass::.ctor(int32, string)
L_000c: stfld class SpoofTest.ExampleClass SpoofTest.Class1::example
L_0011: ldarg.0
L_0012: call instance void [mscorlib]System.Object::.ctor()
L_0017: nop
L_0018: nop
L_0019: ldarg.0
L_001a: ldfld class SpoofTest.ExampleClass SpoofTest.Class1::example
L_001f: isinst SpoofTest.IExample
L_0024: stloc.0
L_0025: ldloc.0
L_0026: ldnull
L_0027: ceq
L_0029: ldc.i4.0
L_002a: ceq
L_002c: stloc.1
L_002d: ldloc.1
L_002e: brtrue.s L_003d
L_0030: nop
L_0031: ldstr "This does not compute"
L_0036: call void [System]System.Diagnostics.Debug::WriteLine(string)
L_003b: nop
L_003c: nop
L_003d: nop
L_003e: ret
}
Now, compare this to what happens if I change ExampleClass to implement IExample. The IL changes to this
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 3
.locals init (
[0] class SpoofTest.IExample iexample,
[1] bool CS$4$0000)
L_0000: ldarg.0
L_0001: ldc.i4.1
L_0002: ldstr "Test"
L_0007: newobj instance void SpoofTest.ExampleClass::.ctor(int32, string)
L_000c: stfld class SpoofTest.ExampleClass SpoofTest.Class1::example
L_0011: ldarg.0
L_0012: call instance void [mscorlib]System.Object::.ctor()
L_0017: nop
L_0018: nop
L_0019: ldarg.0
L_001a: ldfld class SpoofTest.ExampleClass SpoofTest.Class1::example
L_001f: stloc.0
L_0020: ldloc.0
L_0021: ldnull
L_0022: ceq
L_0024: ldc.i4.0
L_0025: ceq
L_0027: stloc.1
L_0028: ldloc.1
L_0029: brtrue.s L_0038
L_002b: nop
L_002c: ldstr "This does not compute"
L_0031: call void [System]System.Diagnostics.Debug::WriteLine(string)
L_0036: nop
L_0037: nop
L_0038: nop
L_0039: ret
}
You'll obviously notice, at this stage, that the isinst check is no longer there.
|
|
|
|
|
Thanks, Pete, that's a satisfyingly "deep" answer !
«I want to stay as close to the edge as I can without going over. Out on the edge you see all kinds of things you can't see from the center» Kurt Vonnegut.
|
|
|
|
|
You're welcome my friend. I like going into the innards of the code, so a question like this was a golden opportunity for me.
|
|
|
|
|
Is there a way to get OAuth2 access token without prompting user for UserID an Password. I mean, from back end accept the authorization and authentication request silently without prompting Website?
|
|
|
|
|
Considering the website will probably NOT trust your users local account authority on their own workstations, no.
The entire reasons for entering a username and password is so that the user can prove to the system that they are who they way they are. The system has to have a "trusted authority" to validate those credentials against.
|
|
|
|
|
TcpClient tClient = new TcpClient("gmail-smtp-in.l.google.com", 25);
string CRLF = "\r\n";
byte[] dataBuffer;
string ResponseString;
NetworkStream netStream = tClient.GetStream();
StreamReader reader = new StreamReader(netStream);
ResponseString = reader.ReadLine();
/* Perform HELO to SMTP Server and get Response */
dataBuffer = Encoding.ASCII.GetBytes("HELO KirtanHere" + CRLF);
netStream.Write(dataBuffer, 0, dataBuffer.Length);
ResponseString = reader.ReadLine();
dataBuffer = Encoding.ASCII.GetBytes("MAIL FROM:<youremail@gmail.com>" + CRLF);
netStream.Write(dataBuffer, 0, dataBuffer.Length);
ResponseString = reader.ReadLine();
/* Read Response of the RCPT TO Message to know from google if it exist or not */
dataBuffer = Encoding.ASCII.GetBytes("RCPT TO:<senderemail@domainname.com>" + CRLF);
netStream.Write(dataBuffer, 0, dataBuffer.Length);
ResponseString = reader.ReadLine();
if (GetResponseCode(ResponseString) == 550)
{
MessageBox.show("Mai Address Does not Exist !
Original Error from Smtp Server :" + ResponseString);
}
/* QUITE CONNECTION */
dataBuffer = BytesFromString("QUITE" + CRLF);
netStream.Write(dataBuffer, 0, dataBuffer.Length);
tClient.Close();
// write a sub procedure for return status of email which is valid or not
private int GetResponseCode(string ResponseString)
{
return int.Parse(ResponseString.Substring(0, 3));
}
|
|
|
|
|
Not entirely sure, but I think their rationale is to prevents bots from grabbing valid emails.
Best,
John
-- LogWizard Meet the Log Viewer that makes monitoring log files a joy!
|
|
|
|
|