Work with Custom Attributes on my C# POCO class - c#

In my project I have one class called Area like below.
The property "CodArea" I want to put one custom attribute like [NaoSelecionarAttr(true)].
This is working fine but when I create one instance of the class I can not get this custom attribute. Something like this:
Area areaPoco = new Area();
areaPoco.CodArea.GetType().GetCustomAttributes(typeof(NaoSelecionarAttr),true).ToList();
[Serializable]
public class Area
{
#region Private Members
private decimal _numChave;
private string _codArea;
public Area()
{
_numChave = 0;
_codArea = null;
}
public Area(decimal pNumChave, string pCodArea)
{
NumChave = pNumChave;
CodArea = pCodArea;
}
public virtual decimal NumChave
{ get { return _numChave;}
set { _numChave = value;}
}
[NaoSelecionarAttr(true)]
public virtual string CodArea
{
get { return _codArea; }
set { _codArea = value;}
}
}
public class NaoSelecionarAttr : Attribute
{
public bool NaoSelecionar { get; set; }
public NaoSelecionarAttr(bool pSim) { this.NaoSelecionar = pSim; }
}
}

There are some problems with your code.
The first problem in the code is that you are calling the default constructor on Area, which initializes _codArea to null. And then you try to call GetType on it, which fails with a NullReferenceException, as expected.
The second problem is that you want an attribute of a property of a class. So you must inspect (or reflect) the class, not the property. You see, when you write areaPoco.CodArea... the compiler resolves it to the result of your get expression, in this case, the field _codArea. By calling GetType() on _codArea, what you retrieve is a String type, not your Area type. I know this may seem confusing at first, but properties aren't types, so you can't reflect on them.
What you should do, then, is:
Area areaPoco = new Area();
NaoSelecionarAttr attr = (NaoSelecionarAttr) (areaPoco.GetType().GetProperties().Single(p => p.Name == "CodArea").GetCustomAttributes(typeof(NaoSelecionarAttr), true).Single());
bool naoSelecionar = attr.NaoSelecionar;
If I may, I want to give you some tips as well:
Your notation for the non-default constructor seems reminiscent of C/C++. There usually isn't a good reason to stick a "p" prefix in the parameters.
Instead of NaoSelecionar, which is a negative property, I recommend you work with "Selecionar". The deal is that you can easily confuse a negative sentence with its correspondent positive one. A month from now you will ask, "ok, the parameter is false, so should I select or not this property?". False usually means NOT, so, your default interpretation would be not to select something when the property is false.
Your default constructor is initializing a property to null. Just as I described above, this can result in bugs. Either initialize it to a default value (string.Empty), or remove the default constructor and use only the one that requires the user to provide a value to string. And validate those parameters as well -- the user might provide again a null to the string. (An object should be valid when first constructed)
One final tip. Your NaoSelecionar attribute gets a boolean parameter. The last bullet was exactly about that -- you can confuse whether having a true property for your attribute means "não" or "sim". Well, why don't you simply remove the parameter and then work with a negative parameter? There's no need to pass true or false to NaoSelecionar, since all you need to do is iterate through your class and find which properties have this attribute applied to them.

Why do you use areaPoco.CodArea.GetType()? I think you should use areaPoco.GetType(). Because your custom attribute belongs to the Area class, not to the string.

Related

How does PropertyDescriptor.ResetValue Method determine default value of property

I have implemented a custom class and tried to set its default value by calling PropertyDescriptor.ResetValue Method. When i make some researches in internet, i saw a link in msdn about this method, its usage and how can be used.
http://msdn.microsoft.com/en-us/library/system.componentmodel.propertydescriptor.resetvalue.aspx
According to this link, msdn document says:
This method determines the value to reset the property to in the following order of precedence:
1- There is a shadowed property for this property.
2- There is a DefaultValueAttribute for this property.
3- There is a "ResetMyProperty" method that you have implemented, where "MyProperty" is the name of the property you pass to it.
Second methodology does not correspond to my needs. On the other hand, there are not enough usage samples of first and third items.
Could you please explain expecially third one?
I don't know about the first option (I suspect it's to do with declaring one property in a base class and a "new" property in a derived class), but the third seems pretty simple to me:
public class Foo
{
public string Name { get; set; }
public Foo()
{
ResetName();
}
public void ResetName()
{
Name = "Some default value";
}
}
The documentation is saying that if you call ResetValue on the PropertyDescriptor for the Name property, it will call the ResetName method on the component.
I've never actually tried this, but that would be my interpretation.
You can retrieve (2) DefaultValueAttribute like this:
public class MyClass
{
[DefaultValue("my default value")]
public string MyVar { get; set; }
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(typeof(MyClass)))
string defaultValue = descriptor.Attributes.OfType<DefaultValueAttribute>().First().Value.ToString();

struct with string member? Invalid default instance acceptable?

Is this a good candidate for a struct?
Consider this immutable struct example where the constructor validates input and stores the validated data as a single "routing code":
struct RoutingCode
{
private readonly string routingCode;
RoutingCode(string prefix, string service, string sender)
{
// Validate prefix, service, sender strings
// ...
if (isInvalid) throw ArgumentException();
//
this.routingCode = prefix + service + sender;
}
// Gets the validated routing code.
public string Routing
{
return this.routingCode;
}
public int RoutingLength
{
return this.routingCode.Length;
}
}
This simplified example appears to me to be a good candidate for using a struct instead of a class:
It is immutable.
It represents a singular value.
The instance size is small.
The problem is that all structs have an implicit default constructor. In this example, the default constructor RoutingCode() would instantiate an object where the Routing property returns null—which is an invalid routing code. This is a different from other structs such as Point or BigInteger where the backing fields contain a very logical and valid "zero" for default instances.
In addition to not ensuring a valid routing code, the RoutingLength property throws a NullReferenceException if called on a default instance.
What are the arguments for keeping this a struct versus making it a class?
You can easily solve your default value problems:
struct RoutingCode
{
private readonly string routingCode;
RoutingCode(string prefix, string service, string sender)
{
// Validate prefix, service, sender strings
// ...
if (isInvalid) throw ArgumentException();
this.routingCode = prefix + service + sender;
}
public string IsValid
{
get { return this.routingCode != null; }
}
// Gets the validated routing code.
public string Routing
{
get { return this.routingCode; }
}
public int RoutingLength
{
get { return this.routingCode == null ? 0 : this.routingCode.Length; }
}
}
OK, now none of the properties throw exceptions and you have a way to tell if the value is invalid. The question at hand is whether or not this is a good candidate for a struct. You are right that it is (1) immutable, (2) small, and (3) logically a value. If you're willing to live with the fact that you can represent an invalid value, then this is probably a good candidate for a struct.
A better question though is: is there a good reason for this not to be a class? Rather than looking for objections to making it a struct, look for objections to making it a class.
It's possible for a hidden-field struct to have uninitialized instances behave as though they holds any particular desired value [the default value must be the same for all uninitialized instances of a given type]. Simply have each property accessor or method check whether the type holds the system default value and, if so, substitute the desired default value instead.
If one wanted to allow code to create an instance where Routing was null and not have such an instance assume that Routing was the default value, one could have the type declare a static string equal to a new GUID (or something else which isn't going to appear elsewhere), and then modify the constructor and get methods:
static string stringRepresentingNull = Guid.NewGuid().ToString();
RoutingCode(string wholeString)
{
if (wholeString == null)
wholeString = stringRepresentingNull;
this.routingCode = wholeString;
}
public string Routing
{
get {
if (this.routingCode == null)
return "12-3456-789"; // Default routing string
else if (Object.ReferenceEquals(routingCode,stringRepresentingNull)
return null;
else
return routingCode;
}
Note that even if outside code somehow manages to guess the GUID that is associated with the type, there's no way for outside code to generate a string where ReferenceEquals will match stringRepresentingNull.
On a similar vein, if one wanted to have an int property with a default value of 123, one could store backingField=(desiredValue ^ 123) and have the property getter yield backingField ^ 123.
The question of whether the type should be a struct or a class largely boils down to one of whether one wants to have the default value of the type behave as a null, or as a valid value. If one wants a null default, use a class. If one wants a valid default, use a struct.

What is the meaning of "get"? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
In C# what does this code with “get” mean?
I'm using open source project. In this project there is function.
public virtual ICollection<Customer> AffiliatedCustomers
{
get
{
return _affiliatedCustomers ?? (_affiliatedCustomers = new List<Customer>());
}
protected set { _affiliatedCustomers = value; }
}
I don't understand what is the meaning of "get".
Can you please explain this function.
AffiliatedCustomers is a property.
The get defines the property getter, which is a method used internally to return the value by the property. It allows you to use this given an instance of the class like so:
var customers = theClass.AffiliatedCustomers; // Looks like a field, but is a property
Properties can also have a set section, as well, as this one does (protected set { _affiliatedCustomers = value; }), which gives you control over what happens when you set the value via the Property.
For details, see Properties in C#.
This is not a function. It is a property. A property is basically a fancy wrapper for some variable. For example, declaring the following property:
public string SomeProperty { get; set; }
will actually compile to something like this:
private string backing_SomeProperty;
public void set_SomeProperty(string value)
{
backing_SomeProperty = value;
}
public int get_SomeProperty()
{
return backing_SomeProperty;
}
That's an example of an automatic property. Of course, you can also define the getter and setter methods yourself like this:
public string SomeProperty
{
get
{
// some logic code here
// then return some value
}
set
{
// some logic code here
// then set some value
}
}
This is a property,
Quoted by msdn:
Properties are members that provide a flexible mechanism to read, write, or compute the values of private fields. Properties can be used as though they are public data members, but they are actually special methods called accessors. This enables data to be accessed easily while still providing the safety and flexibility of methods.
Please refer to this link for more:
http://msdn.microsoft.com/en-us/library/x9fsa0sw(v=vs.80).aspx
Properties have a getter and a setter - their purpose is obvious (to get and set the value of the property).
When you use auto properties, there is still a get and a set, but the backing variable is automatically implemented for you. In the example you have given the author of the code has chosen to have their own implementation of the get - in this case to automatically initialise the member variable the first time the property is accessed.

Is it right to have a setter to set different type than the property type?

e.g.
[XmlAttribute("Type")]
public string DataTypeString
{
get
{
return _dataType.ToString();
}
set
{
_dataType = Type.GetType(value);
}
}
private Type _dataType;
public Type DataType
{
get { return _dataType; }
set { _dataType = value; }
}
In the above code, first property type is string, however the setter sets, the _dataType which is of System.Type
You can and often benificial to do so for get properties.
Type conversion in set properties likley be more contraversial. Properties are normally expected to be lightweight, not to throw exceptions and normally x.YYY=newValue; expected to result in x.YYY==newValue to be true - these may be hard to achieve if type conversion happens.
I.e. in your particular example allowing to set type by string as property feels like a bad idea - what is expected behavior of x.DataTypeString="42";? You may want to consider some other way to enable XML serialization of your property...
Sure you can. That's the purpose of the properties. The user of the property doesn't need to know what's behind it. He/she just sets or gets a string and that's all they need to know.
I guess its ok, but I would prefer to just do this, which less odd and less verbose:
public void SetDataType(string value) {
_dataType = Type.GetType(value);
}
public void SetDataType(Type value) {
_dataType = value;
}
public Type DataType { get; private set; }
As was already mentioned, it seems rather odd to have two getter/setter pairs for the same private variable.
It's hard to say without knowing the purpose of this class. But in general, I think I'd be confused by having two properties with the same backing field (so that changing one affects the other).
There are exceptions though. For example, in a Circle class, I would find it perfectly reasonable to have both a Radius property and a Diameter property. So again, it kind of depends on the purpose of your class.
Also, in the example you provided, it doesn't seem like the DataTypeString property provides much benefit. If you remove it, callers could achieve the same effect by simply calling
foo.DataType = Type.GetType("System.Int32");
or
string dataTypeString = foo.DataType.ToString()
.

Default value of a property

If you have an object like this:
public class Foo
{
private int _id;
public int id
{
get { return _id; }
set { _id = value; }
}
private string _name;
public string name
{
get { return _name; }
set { _name = value; }
}
}
And you want to initialize id to -1 and name to String.Empty what is the best practice? (and why)
Doing:
private int _id = -1
Or
Setting _id = -1 and name = String.Empty in the constructor?
This is more of a style question than anything else. There are only a few cases where it is a functional issue
When you have many constructors which all initialize the fields to the same value. At that point you have redundant code and should either refactor your constructors or use field initializers.
Don't use a field initializer if it depends on the value of another field in the same class hierarchy. In the abscence of partial classes the outcome is predictable but still can throw people for a loop..
depends on when you want it to be set...
private int _id = -1
will initialize _id before the constructor is called.
The field approach is concise, which gets a lot of votes, but my preference (for simple properties) would be to use auto-properties, in which case you are forced to use the constructor:
public Foo() {
Id = -1;
Name = "";
}
public int Id {get;set;}
public string Name {get;set;}
You might also consider using [DefaultValue(-1)] etc, which helps designers and serializers, but this does not affect the initial value of an auto implemented property (or a regular property) - it is additional info only.
Setting it "inline" rather than using the constructor seems, to me, to indicate intention better. Functionally they're the same.
A CLR wizard might correct me, but I believe those two approaches are functionally identical, but you could make an argument that setting the default values in the constructor is more explicit and obvious, but also a bit messier.
Inline initialization is added to the top of the constructor by the C# compiler so there is really no difference. Personally I prefer always adding constructors even if it is only a default constructor.
It's mainly the question of style preference. I usually assign them in the constructor, because it is a sane place for all the data and procedures that take place when object is instantiated.

Categories

Resources