C# Custom Attribute Alternatives - c#

Currently, I've created a class with ~30 properties to be set. This is done to build up a URL request later on(ie, "http://www.domain.com/test.htm?var1=a&var2=b...&var30=dd").
The issue I'm facing is the property names don't necessarily match the query variable names(this is intended to be different). For example, I may have a variable titled "BillAddress", whereas the query variable will need to be "as_billaddress".
I have no control over the query variable naming scheme as these are set at an external source.
One possible solution I've used is creating a custom attribute and decorating the properties with their respective query counterparts:
[CustomQueryAttribute("as_billaddress")]
string BillAddress{get;set;}
To retrieve the attribute though, requires a little reflection and due to the larger number of properties, I was curious if there is a neater way to accomplish this functionality. Not so much as setting/retrieving custom attributes without reflection, but being able to tie an alternate string variable to any property.
I've also pondered about setting each variable up as a sort of KeyValuePair, with each key representing the query counterpart, but I didn't get too far in that thought.
To summarize/clarify my above backstory, what would you do to associate a string with a property(not the value of the property)?
As always, any comments are greatly appreciated.

I would probably stick with a custom attribute, but the other potential option would be to do something like hold a static Dictionary that had string and property info (or property name), so you could get/set the property directly via this.
Something like:
static Dictionary<string, PropertyInfo> propertyMap = new Dictionary<string, PropertyInfo>();
static MyClass()
{
Type myClass = typeof(MyClass);
// For each property you want to support:
propertyMap.Add("as_billaddress", MyClass.GetProperty("BillAddress"));
// ...
}
You could then just do a dictionary lookup instead of using reflection in each call... This could also be setup fairly easy using configuration, so you could reconfigure the mappings at runtime.

A custom attribute seems like the best option to me - the framework seems to do this a lot as well (specifically with serialization).

If you look at popular ORM mappers then nearly all either use custom attributes or some kind of XML mapping file. The advantage of the latter is that you can modify the mapping without recompiling your application - the downside is that it hurts performance. However, I'd say your choice seems perfectly reasonable.

Related

c# BsonSerializer: deserialization through backing fields

I'm starting to work with MongoDB using official c# driver. The problem is that I can't find a way to make bsonseriazer use fields (not properties) for setting the deserialized data and at the same time being able to use LINQ Api.
When mapping my class, I use BsonClassMap.FieldMap(). But this doesn't allow to use LINQ, since public properties remain unmapped.
Is there a way in BsonSerializer to do mappings based on properties, but at the same time specify that these should be set directly via their backing fields?
The reason I want to use fields for deserialization, is to omit custom validation rules that might be checked in setter.
I think you should keep those validation rules even when the data comes from your own database. It's much cleaner, less bug-prone and is more secure.
You can create your own BsonSerializers (or extend an existing one) that act which ever way you want. I've made several of those and it's really simple.
You can have a bool _isInitialized = false; in your DTOs that you set to true right after you get items from the MongoDB driver and forgo the validation rules until it is set.
I don't see another way to "split" the mapping to both the properties (for Linq) and data members (for serialization) and I recommend the first option.

Is is a good practice to store propery names in a public constant string?

In order to protect ourself from failure because of any renaming of properties (Let's say you regenerate your poco classes because you have changed some column names in the relevant Db table) is it a good practice to decalre constant strings that keep the property names inside?
public const string StudentCountPropertyName = "StudentCount";
public int StudentCount {get;set;}
For example: Think about a DataBinding; where you type the property name in the DataFieldName attribute explicitly.
Or this is not a good idea and there is a better and still safer way?
It is always a good idea IMHO to move any 'magic strings' to constants.
You could consider using lambda expressions to 'pick' your properties, for example:
GetDataFieldName(studentCollection => studentCollection.Count)
You will have to implement GetDataFieldName yourself, using a bit of reflection. You can look at HtmlHelperExtensions from MVC to see how it can be done. This will be the most safe approach, which gives you compile-time errors when something goes wrong and allows easy property renaming using existing refactoring tools.
From one point of view: if you using this property name multiple times it is good practice. It will help for sure with the refactoring and when you for example change property name you see that you need change this const also.
From another point of view i guess it will be ugly when my class with 10 properties will have 10 additional consts. Another solution if you want avoid consts or explicit name typing can be getting property names through the reflection.
Use such approach or not you should decide yourself.
I think it's a common practice to put this "magical string" or "magical numbers" in some kind of strong typed store.
Something you can consider is to code it in a Aspect Orientied Way.
For example the calls to notifypropertychagned can be realized with an attribute implemented with an aop framework, like PostSharp .
[NotifyChange]
public int Value {get;private set}
This tools also have some downsides but i think there are scenarios where they can save you a lot of work
I do not know if I fully understand your question, but if I understand it right I would have used an attribute for that, an example could be the use of ColumnAttribute in Linq which you use to map a property to a specific column in a database (http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.columnattribute.dbtype.aspx), like in this example:
[Column(Storage="ProductID", DbType="VarChar(150)", CanBeNull=False)]
public string Id { get; set; }
And I would never use DataFieldName, I would DataBind to the strongly typed objects (and of course also make an interface to the class that uses the property above so I easily can change the implementation in the future ;))
I suppose if the names are used in many places then it would be easier just to change them in this one place and use the constant as described in your comment.
However, a change to a database column name and object property name implies a change to your conceptual data model. How often do you think this is going to happen? In the early stages of a project, whilst conceptual modelling and implementation are paralellised across a dev team, this may be quite fluid, but once the initial conceptual modelling is done (whether this in a formalised conscious manner or just organically), it's usually quite unlikely that fundamental things like these are going to change. For this reason I think it's relatively unusual to have do this and the technique will only be productive in edge cases.
Absolutely. It's a good idea.
By the way, I would argue that these kind of things could be better stored in application settings, because you can define such things in an application configuration file later by overriding these settings.
Doing that this way you'll avoid re-compiling if some database, POCO or whatever changes, and as in newer Visual Studio versions like 2010, you can tell it to generate settings with "public" accessibility, you can share strongly-typed settings with any assembly that reference the one containing them.
At the end of the day, I'd change your code with DataBindingSettings.StudentCountPropertyName instead of a constant.
Easy to manage, more re-usable, and readable, as "you configure a data-binding with its settings".
Check this MSDN article to learn more about application settings:
http://msdn.microsoft.com/en-us/library/a65txexh(v=VS.100).aspx

How to design to prompt users for new values for properties of deserialized objects?

Right now, I'm currently serializing a class like this:
class Session
{
String setting1;
String setting2;
...etc... (other member variables)
List<SessionAction> actionsPerformed;
}
Where SessionAction is an interface that just has one method. All implementations of the SessionAction interface have various properties describing what that specific SessionAction does.
Currently, I serialize this to a file which can be loaded again using the default .Net binary serializer. Now, I want to serialize this to a template. This template will just be the List of SessionActions serialized to a file, but upon loading it back into memory at another time, I want some properties of these SessionActions to require input from the user (which I plan to dynamically generate GUI controls on the fly depending on the property type). Right now, I'm stuck on determining the best way to do this.
Is there some way I could flag some properties so that upon using reflection, I could determine which properties need input from user? Or what are my other options? Feel free to leave comments if anything isn't clear.
For info, I don't recommend using BinaryFormatter for anything that you are storing long-term; it is very brittle between versions. It is fine for short-lived messages where you know the same version will be used for serialization and deserialization.
I would recommend any of: XmlSerializer, DataContractSerializer (3.0), or for fast binary, protobuf-net; all of these are contract-based, so much more version tolerant.
Re the question; you could use things like Nullable<T> for value-types, and null for strings etc - and ask for input for those that are null? There are other routes involving things like the ShouldSerialize* pattern, but this might upset the serialization APIs.
If you know from start what properties will have that SessionAction, you must implement IDeserializationCallback and put to those props the attribute [NonSerialized]. When you implement the OnDeserialization method you get the new values from the user.

Should I use values or keys?

I am warpping an ArcGIS IFeature object with a class that has my required properties to get and set them easily.
Basically, the get and set operations just use feature.get_value(index) and feature.set_value(indes, value), and expose the strongly typed value.
I have several fields that use a domain (basically, an IDictionary<string, object>) to represent common properties across the application.
At first I figured I would only use the keys of the domain (which are normal int values) in my wrapping class, and use the domain in my ToString() method, to translate to strings for the UI.
Later I figured out I can use strings in my applicaiton (which makes it easier to pass around nulls, as the actual domain fields are nullable most of the time), and only change those fields' getters and setters to use GetDomainValue(index) and SetDomainValue(index, value) method that will translate between the key and value to/from the underlying feature object.
What approach do you think is better? I figured the string approach is a bit more "persistent ignorant", as my class doesn't care how the values are being saved, just their string representation.
On the other hand, it makes the code jump through loops a bit - instead of returning what's in the feature, every getter needs to iterate the domain.
You might want to think about representing your domain fields with Nullable< Int32>. This would give you a way to represent features that have a domain value specified but it also allows you to directly specify null where appropriate.
I ended up sticking with the domain values, so that I can also verify that the calling code passed a valid value.

Fastest way to use reflection for converting datareader to list

I am using reflection to convert datareader into the generic collection list. Can anybody
suggest me the best way to implement reflection for this? I want the fastestway?
I assume what you want to do is something like:
List<MyClass> list = LoadFromDataReader<MyClass>(dataReader);
with:
class MyClass
{
[DataField("FirstName")] public string FirstName { get; set; }
[DataField("LastName")] public string LastName { get; set; }
}
I do this by:
Using Type.GetProperties and PropertyInfo.GetCustomAttribute to put together a dictionary mapping field names to PropertyInfo objects
Calling PropertyInfo.SetValue on each field in each record
You can cache the results of step (1), since the field/property mapping isn't going to change during the life of the application.
If performance is a problem (i.e. if step (2) turns out to be a bottleneck), then you have to avoid using reflection and generate code to set the properties directly. A couple of alternative improvements:
Use System.CodeDom to generate a C# class containing code to set the properties according to the respective fields on the IDataReader. Note that System.CodeDom invokes the csc.exe compiler in the background, so you need to generate this code once at startup and re-use it on each call.
Use System.Reflection.Emit.DynamicMethod to generate IL code that sets properties. Less runtime overhead than System.CodeDom, but since you're generating raw IL, this is much harder to write and debug. Use as a last option.
This really depends on exactly what you are looking at doing. I implement a object/interface process where I create information objects that hold the data that is returned. I then use an interface IFillable or something similar that passes a DR to the object and the object does the hydration from the DR.
This way I avoid the need for reflection, and the performance is great. I then have a few generic helper methods for Fill and FillCollection.
I got the idea based on stuff inside the CBO object of the DotNetNuke framework. It also implements a reflection method as well, that is fairly decent in performance.

Categories