i want to use the setter to auto-correct the value and want to use the RequiredAttribute too. But in this case the RequiredAttribute do not work, because the setter is not empty.
So, why have the setter to be empty?
[Required(AllowEmptyStrings = false, ErrorMessage = "The Name cannot be empty. Please correct.")]
public String Name //{get; set;} <- Required works fine...
{
get { return _name; }
set // <- Required did not work...
{
String setValue = Regex.Replace(value, #"^\d+", "");
setValue = Regex.Replace(setValue, #"[^a-zA-Z0-9_]+", "_");
_name = setValue;
}
}
Your assumption is actually incorrect. You can use a custom setter with the required attribute.
void Main()
{
var test = new Test();
Validator.ValidateObject(test, new ValidationContext(test));
}
public class Test
{
private string _name;
[Required(AllowEmptyStrings = false, ErrorMessage = "The Name cannot be empty. Please correct.")]
public String Name
{
get { return _name; }
set
{
String setValue = Regex.Replace(value, #"^\d+", "");
setValue = Regex.Replace(setValue, #"[^a-zA-Z0-9_]+", "_");
_name = setValue;
}
}
}
This quick and dirty test throws your Required validation message.
Related
C# System.Xml doesn't serialize tag if the name is "value". Is it feature or bug?
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)]
public System.Nullable<decimal> value {
get {
return this.valueField1;
}
set {
this.valueField1 = value;
}
}
Setting the request:
filterGroup.numberFilters[0] = new numberFilter() {
field = "ID",
operation = numberOperation.EQUAL,
value = 99
};
The serialized request:
<numberFilters>
<field>ID</field>
<operation>EQUAL</operation>
</numberFilters>
If I change this tag name to something other, the result is correct
<numberFilters>
<field>ID</field>
<operation>EQUAL</operation>
<valueKA>99</valueKA>
</numberFilters>
Your property definition looks wonky. "value" is generally a reserved keyword in the setter. Suggest you rename public property to Value, and keep backing field valueField1.
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)]
public System.Nullable<decimal> value { <-- this
get {
return this.valueField1;
}
set {
this.valueField1 = value; <-- and this cant be the same.
}
}
I found the solution.
There is an another getter/setter in the generated class: valueSpecified.
This needs to be set to 'true'
filterGroup.numberFilters[0] = new numberFilter() {
field = "ID",
operation = numberOperation.EQUAL,
value = 99,
valueSpecified = true
};
I have a class say ConstructionSet which is having name property having computed inside get method like as below
public class ConstructionSet
{
[Key]
public Guid Id { get; set; }
public string Name
{
get
{
string climateZonesCsv = (ClimateZones != null && ClimateZones.Any())
? $" - {string.Join(", ", ClimateZones.Select(a => a.Name))}"
: "";
var sourceOfData = !string.IsNullOrEmpty(SourceOfData?.Edition)
? $"{SourceOfData.Name}, {SourceOfData.Edition}"
: SourceOfData?.Name;
return $"{sourceOfData} - {ConstructionMassingType?.Name}{climateZonesCsv}";
}
set { }
}
.......
.......
}
and then I am doing some operations like cloning this ConstructionSet object and appending some text like "copy" to the name property of ConstructionSet after deepclone and it is looks like as below
var targetDhpConstructionSets = sourceDhpConstructionSets.ConvertAll(
dhpcs =>
{
var newDhpConstructionSet = new DesignHubProjectConstructionSet(dhpcs);
var clone = DeepCloner.Clone(dhpcs.SectionObjectRaw);
clone.Name += " (Copy)";
newDhpConstructionSet.AddPatch(employeeContext, clone);
newDhpConstructionSet.IsDefault = dhpcs.IsDefault;
newDhpConstructionSet.Warnings = dhpcs.Warnings;
return newDhpConstructionSet;
});
and below is the image where it shows dhpcs.SectionObjectRaw is indeed a ConstructionSet class object and if i observe the clone object name property value after this line clone.Name += " (Copy)"; the Copy text is not appended.
Could any one please let me know why i am not seeing the appended values to the name property of ConstructionSet
many thanks in advance
because your setter does literally nothing:
set { }
Since your getter obtains several pieces of information on-the-fly, it's not obvious how to change your design to add on arbitrary text to what the getter provides. You could have a "suffix" property that gets appended to the strings that are currently returned, for example. Or have a backing field that the getter populates if it is null, then have the setter change the value of the backing field.
Based on your comments I would probably go with a backing field:
private string _Name;
public string Name
{
get
{
if(this._Name == null) {
string climateZonesCsv = (ClimateZones != null && ClimateZones.Any())
? $" - {string.Join(", ", ClimateZones.Select(a => a.Name))}"
: "";
var sourceOfData = !string.IsNullOrEmpty(SourceOfData?.Edition)
? $"{SourceOfData.Name}, {SourceOfData.Edition}"
: SourceOfData?.Name;
_Name = $"{sourceOfData} - {ConstructionMassingType?.Name}{climateZonesCsv}";
}
return _Name
}
set { _Name = value }
}
When I write the code like the methods below my fields get initialized correctly and the application works fine.
private string username;
private string password;
public string Password
{
get { return password; }
set { password = value; }
}
public string Username
{
get { return username; }
set { username = value; }
}
public Authenticate()
{
this.username = "njabulo";
this.password = "12345";
}
Before writing it like this I had written the code in the following fashion and the fields didn't get initialized:
private string username;
private string password;
public string Password
{
get { return password; }
set { password = "njabulo"; }
}
public string Username
{
get { return username; }
set { username = "12345"; }
}
I would like to know what exactly is causing the error in the second method. I think the value on the set property stands for anything that may be thrown at the property and I am giving it an actual value.
There is no reason to Set to a literal value, you may as well do
get { return "njabulo"; }
If you are using C# 6 then you can initialize like:
public string Password {get; set;} = "njabulo";
Then it will initialize, but not always stay that value if you set it later.
When you define a property, with getter or setter, it means that the code for getter or setter only execute when any of these actions occurred.
In the second example you haven't called the setter yet.and there is no reason to specify setter with a content value.
The first example is fine bcoz you have done the followings
1.Defined properties with back end fields.
2.initialised back end fields
But in the second one you haven't made initialisation.
The purpose of set is to allow setting the value of that property, like this:
var x = new WhateverYourClassIsNamed();
x.Username = "ABC";
You would normally write the property like this:
public string Username
{
get { return username; }
set { username = value; }
}
That way if someone calls
x.Username = "newusername";
then when the set method is called, value is "newusername"; That's how you can set a property on your class. You don't have to declare a variable named value. That automatically refers to whatever value is used when you call set.
If you do this:
set { username = "12345"; }
Then it doesn't matter what value you try to set. You could call
x.Username = "99999"
or any other value, but it's always going to set username to "12345".
Usually when we say "initialize" we mean values that are set when the class is first created. If that's what you had in mind you could do this:
private string username;
private string password = "12345"; //This set whenever you create
//a new instance of the class
public string Password
{
get { return password; }
set { password = value; }
}
public string Username
{
get { return username; }
set { username = value; }
}
or do as Crowcoder suggested,
public string Password {get; set;} = "12345";
That's a newer, more convenient syntax that does the same thing.
The correct initialization is the first method, or make it shorter using automatic property. The second method, before anybody call "set", your Password or Username is still null :
public string Password { get; set; }
public string Username { get; set; }
public Authenticate()
{
Username = "njabulo";
Password = "12345";
}
I add more because of your comments above (compare value), you can use it like this:
public class Authenticate
{
private string _password;
private string _username;
public Authenticate()
{
_password = "mypassword";
_username = "myusername";
}
public string Password
{
get { return _password; }
set
{
if (_password != value) // Compare it here
_password = value;
}
}
public string Username
{
get { return _username; }
set
{
if (_username != value) // Compare it here
_username = value;
}
}
}
The default value of the following configuration property is obvious. It is "Arial":
[ConfigurationProperty("name", DefaultValue = "Arial", IsRequired = true)]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
But, what if I remove the "DefaultValue" part, as follows?
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
In Visual Studio, the value of the DefaultValue property on the attribute is listed as {object}, and if I call .ToString() on it, I get "System.Object".
How do I check whether or not a default value has actually been specified on the attribute?
According to the reference source, it looks like an object is created privately, meaning it cannot be accessed:
private object _DefaultValue = ConfigurationElement.s_nullPropertyValue;
(source: http://referencesource.microsoft.com/#System.Configuration/System/Configuration/ConfigurationPropertyAttribute.cs,31)
However, I was able to fix the problem as follows:
var isDefaultSpecified = propertyAttribute.DefaultValue != null && propertyAttribute.DefaultValue.GetType() != typeof(object);
In C#, if we have a class 'Employee' and it will have a property called 'Code' that must consist of 7 characters in the following format: (A-Z) + (1-9)+(0-1)+(0001-9999)
for example 'Code' = A501234 or Z910002
So if we make a property 'Code' in the Class 'Employee' is there any way to force developer when 'Code' is set, to check if it is in the prev format or at least force him to set it to 7 characters, so that, for example, it can cause compiler or build errors?
Thanks in advance for expected cooperation
public struct Code
{
public readonly String Value;
public Code(String value)
{
if (value == null) throw new ArgumentNullException("value");
if (value.Length != 7) throw new ArgumentException("Must be 7 characters long.");
// Other validation.
Value = value;
}
}
public string Code
{
set
{
if (value.Length != 7)
{
throw new ArgumentOutOfRangeException(...)
}
// other validation
_code = value;
}
}
Validating parameter values/formats at runtime could also be accomplished using the
Validation Application Block from the MS Enterprise library or something similar.
You would basically specify your validation rules using attributes,
[StringLengthValidator(1, 50, Ruleset = "RuleSetA",
MessageTemplate = "Last Name must be between 1 and 50 characters")]
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
[RelativeDateTimeValidator(-120, DateTimeUnit.Year, -18,
DateTimeUnit.Year, Ruleset="RuleSetA",
MessageTemplate="Must be 18 years or older.")]
public DateTime DateOfBirth
{
get { return dateOfBirth; }
set { dateOfBirth = value; }
}
[RegexValidator(#"\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*",
Ruleset = "RuleSetA")]
public string Email
{
get { return email; }
set { email = value; }
}
Code snippet from http://msdn.microsoft.com/en-us/library/dd139849.aspx. Don't know of anything that would check at compile time though.
You can do this in the setter section of the property.
public string Code
{
set
{
if (value.Length != 7)
throw new Exception("Length must be 7.");
_code = value;
}
}
In the setter for the property, you can check the length and throw an error if it is != 7
To check the exact format, you can use regular expressions.
A Regular expression can validate the length and the format all at once.
class Employee
{
// ...
private string code;
public string Code
{
set
{
Regex regex = new Regex("^[A-Z]{1}[1-9]{1}[0,1]{1}[0-9]{3}[1-9]{1}$");
Match match = regex.Match(value);
if (!match.Success)
{
throw new ArgumentException("Employee must be in ... format");
}
code = value;
}
}
// ...
}