Best way to access attributes - c#

I am working on a framework that uses some Attribute markup. This will be used in an MVC project and will occur roughly every time I view a specific record in a view (eg /Details/5)
I was wondering if there is a better/more efficient way to do this or a good best practices example.
At any rate, I have an a couple of attributes e.g:
[Foo("someValueHere")]
String Name {get;set;}
[Bar("SomeOtherValue"]
String Address {get;set;}
What is the most efficient way/best practice to look for these attributes/Act on their values?
I am currently doing something like this:
[System.AttributeUsage(AttributeTargets.Property)]
class FooAttribute : Attribute
{
public string Target { get; set; }
public FooAttribute(string target)
{
Target = target;
}
}
And in my method where I act on these attributes(simplified example!):
public static void DoSomething(object source)
{
//is it faster if I make this a generic function and get the tpe from T?
Type sourceType = source.GetType();
//get all of the properties marked up with a foo attribute
var fooProperties = sourceType
.GetProperties()
.Where(p => p.GetCustomAttributes(typeof(FooAttribute), true)
.Any())
.ToList();
//go through each fooproperty and try to get the value set
foreach (var prop in fooProperties)
{
object value = prop.GetValue(source, null);
// do something with the value
prop.SetValue(source, my-modified-value, null);
}
}

Attribute.GetCustomAttribute and PropertyInfo/MemberInfo.GetCustomAttribute is the recommended way of getting at attribute objects.
Although, I wouldn't normally enumerate all properties with attributes; you generally want to work a particular attribute so you'd just call GetCustomAttribute directly.If you're looking for attributes on any of your properties, enumerating those properties looking for attributes based on GetCustomAttribute() the way you're doing it, is the best way to do it.

There is not really much choice when dealing with attributes - your code is ok and reasonable as is, it is also unlikley to be your main performance concern. The only immediate thing is to drop ToList call as absolutely unnecessary.
Side notes: performance related question should look approximately
"I've measured my code and portion XXX seems to be taking too much time (YYY) . The time goal for this piece of code is ZZZ. Is my way of doing XXX reasonable/where can I improve it?".
Note that in you case you are missing YYY and ZZZ time portions - so you can't really say if it is slow for your case or not. And you may want to start measurements with DB/other IO bound operations as it more likely to speed up your overall code.
After you figured that this attribute related code is main perfomance issue you can consider some sort of caching of results or even code generation of some sort (either through caching lambdas that would set necessary values or even full blown IL generation).

Related

Is it possible to create a class template and select a C# property when the function is called?

Does anyone know if the following is possible to pass in a List<> of objects to a function and specify which property the function should use within each object that its working with ?
I have a class that works with a specific property of an object throughout the class, but I dont want to create multiple copies of the same class to work with different properties of that object. I thought about using Linq, but I dont see a way to specify which property to use in other functions of the manipulation class.
I was thinking there has to be a more elegant way to do this instead of creating the same class to handle each property. I thought about using Reflection to tell the function which property to work with but that gets ugly really quick
Example psuedo code :
class Store
{
int amount;
int id;
int serial;
}
class AggregationMethods
{
bool Has3Values( List<Store> places /* some other param to specify which property to use*/)
{
// do something with Store.amount or Store.id
}
// other functions to work with Store.amount or Store.id or Store.serial
}
In your case, they're all int values - so you could just retain a Func<Store, int> or pass it into each method. It becomes slightly harder if you need to work over multiple types, but we don't really have enough information to comment further.
It's also not clear whether you would expect two have multiple instances of AggregationMethods (e.g. one for amounts, one for IDs etc) or whether these would really be static methods. If you're using instances, then you could keep the projection as a member variable, and apply it within each method.
It's worth noting that the properties you've given probably don't really make sense to apply the same aggregations - for example, while summing amounts makes sense, it's meaningless to sum IDs.

how to iterate through reader for notnull without repeating code over and over

First off, I am new to programming (especially with C#) and thanks for your help.
I have a static web form with about 150 form objects (most checkboxes). I decided to go 1 record per form submission in the sql db. So, for example, question X has a choice of 5 checkboxes. Each of these 5 checkboxes has a column in the db.
I have the post page complete(working) and am building an edit page where I load the record and then populate the form.
How I am doing this is by passing a stored proc the id and then putting all the returned column values into the according object properties, then setting the asp control object to them.
An example of setting the asp controls to the selected value:
questionX.Items[0].Selected = selectedForm.questionX0
questionX.Items[1].Selected = selectedForm.questionX1
questionX.Items[2].Selected = selectedForm.questionX2
As you see, this is very tiresome since there are over 150 of these to do. Also, I just found out if the response is NULL then I get the error that it cant be converted to a string. So, I have added this line of code to get past it:
This is the part where I am populating the returned column values into the object properties (entity is the object):
if (!String.IsNullOrEmpty((string)reader["questionX0"].ToString()))
{entity.patientUnderMdTreatment = (string)reader["questionX0"];}
So, instead of having to add this if then statement 150+ times. There must be a way to do this more efficiently.
First of all, it seems that you are using string.IsNullOrEmpty(value), but this won’t check for the special DBNull value that is returned from databases when the data is null. You should use something more akin to value is DBNull.
The rest of your problem sounds complex, so please don’t be put off if my answer is complex too. Personally I would use custom attributes:
Declare a custom attribute
The following is a skeleton to give you the idea. You may want to use the “Attribute” code snippet in Visual Studio to find out more about how to declare these.
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public sealed class QuestionColumnAttribute : Attribute
{
public string ColumnName { get; private set; }
public QuestionColumnAttribute(string columnName)
{
ColumnName = columnName;
}
}
Use the custom attribute in the entity class
Where you declare your entity class, add this custom attribute to every field, for example where patientUnderMdTreatment is declared:
[QuestionColumn("questionX0")]
public string patientUnderMdTreatment;
Iterate over the fields
Instead of iterating over the columns in the reader, iterate over the fields. For each field that has a QuestionColumnAttribute on it, get the relevant column from the reader:
foreach (var field in entity.GetType().GetFields())
{
var attributes = field.GetCustomAttributes(typeof(QuestionColumnAttribute), true);
if (attributes.Length == 0)
continue;
object value = reader[attributes[0].ColumnName];
if (!(value is DBNull))
field.SetValue(entity, value.ToString());
}
For the first part of your question where you set the ASP controls, you can use a similar strategy iterating over the fields of selectedForm, and this is probably simpler because you don’t need a custom attribute — just take only the fields whose name starts with “questionX”.
this is a quick & easy way of doing it.. there are some suggestions to investigate LINQ, and I'd go with those first.
for (int i = 0; i < 150; i++)
{
if (!String.IsNullOrEmpty((string)reader["questionX" + i.ToString()].ToString()))
{entity.patientUnderMdTreatment = (string)reader["questionX" + i.ToString()];}
}
... though this wouldn't be any good with the
questionX.Items[0].Selected = selectedForm.questionX0
questionX.Items[1].Selected = selectedForm.questionX1
questionX.Items[2].Selected = selectedForm.questionX2
lines
so I hear two questions:
- how to deal with null coming from IDataReader?
- how to deal with multiple fields?
Lets start with simple one. Define yourself a helper method:
public static T IsDbNull<T>(object value, T defaultValue)
{
return (T)(value is DBNull ? defaultValue : value);
}
then use it:
entity.patientUnderMdTreatment = IsDbNull<string>(reader["question"], null);
Now how to map entity fields to the form? Well that really is up to you. You can either hardcode it or use reflection. The difference of runtime mapping vs compile-time is likely to be completely irrelevant for your case.
It helps if your form fields have identical names to ones in the DB, so you don't have to do name mapping on top of that (as in Timwi's post), but in the end you'll likely find out that you have to do validation/normalization on many of them anyway at which point hardcoding is really what you need, since there isn't a way to dynamically generate logic according to the changing spec. It doesn't matter if you'll have to rename 150 db fields or attach 150 attributes - in the end it is always a O(n) solution where n is number of fields.
I am still a little unsure why do you need to read data back. If you need to preserve user's input on form reload (due to validation error?) wouldn't it be easier/better to reload them from the request? Also are entity and selectedForm the same object type? I assume its not a db entity (otherwise why use reader at all?).
Its possible that there are some shortcuts you may take, but I am having hard time following what are you reading and writing and when.
I recommend using the NullableDataReader. It eliminates the issue.

Downcasting in C#

I'm facing a problem that I don't know how to solve and am hoping the community can help.
I'm writing an app that manages "Lead" objects. (These are sales leads.) One part of my program will import leads from a text file. Now, the text file contains lots of potential leads, some of which I will want to import and some of which I won't.
For ease of programming (and use), I'm parsing the text file into a List<Lead> object, and using a DataGridView to display the leads by setting the DataSource property of the DataGridView.
What I want to do is add a column to the grid, called "Import," with a checkbox that the user can check to indicate whether or not each lead should be imported.
My first thought is to derive a class from Lead:
public Class LeadWithImportCheckbox : Lead
{
bool bImport = false;
public bool Import
{
get { return bImport;}
set { bImport = value;}
}
}
However, the parsing engine returns a list of Lead objects. I can't downcast a Lead to a LeadWithImportCheckbox. This fails:
LeadWithImportCheckbox newLead = (LeadWithImportCheckbox)LeadFromParsingEngine;
This is an invalid cast.
The other option I see is to create a constructor for LeadWithImportCheckbox:
public LeadWithImportCheckbox(Lead newlead)
{
base.Property1 = newlead.Property1;
base.Property2 = newlead.Property2;
....
base.Property_n = newlead.Property_n;
}
This is problematic for two reasons. One, the Lead object has several dozen properties and writing this constructor is a PITA.
But worse, if I ever change the underlying structure of Lead, I need to remember to go back and change this constructor for LeadWithImportCheckbox. This is a danger to my code maintenance.
Is there a better way of accomplishing my goal?
or, to avoid the PITA aspect, use reflection... (try this...)
EDIT: use property, not Field as I had originally written...
public class NewLead : Lead
{
public bool Insert;
public NewLead(Lead lead, bool insert)
{
Insert = insert;
foreach (PropertyInfo pi in typeof(Lead).GetProperties())
GetType().GetProperty(pi.Name).SetValue
(this, pi.GetValue(lead,null), null);
}
}
public class LeadListItem
{
public Lead Lead { get; set; }
public bool ShouldImport { get; set; }
}
i.e. don't copy the Lead object's contents, just store a reference to it in a new LeadListItem object, which adds extra info "outside" the original object.
If you want the properties of Lead to appear in the grid, there is almost certainly a way of doing that. Why not ask that question, instead of downvoting me for telling you the right answer to this question!
A couple options you might have missed:
You could update the Lead object itself to have an Import property (that defaults to false).
You could have your "ImportLead" object treat the Lead as payload (even make it generic, if you want), so you don't need the big constructor.
Build a new Lead object list or enumerable that only contains the objects you want to import in the first place.
You can only downcast, if the object to be downcast is really an object of that type.
An easier way to solve your problem would be to have a DisplayLead class, such as:
public class DisplayLead {
Lead lead;
bool bImport;
}
which would also help you separating stored data from their representation in a GUI.
What you want to do is display the checkbox column on your grid and not have it related at all to your Lead objects. You use the marked columns (and possible the original List) to build a new set of List which will be your import list.
Then handle whatever you wish to do with the newly created List.
Edit: One thing to be careful of when working with lists is the fact every class object is actually only a pointer to the class so if you work with the original list and do something like:
List<Lead> Importable = new List<Lead>();
for(int i=0, i++, i<viewGrid.Count)
if(viewGrid[i].CheckedColumn.Checked)
Importable.Add(OriginalList[i]);
That objects will exist in both lists and if you edit data of a Lead on either list both will be changed.
I cannot downcast to something it is not. If the object was instantiated as a Lead, then it can't be downcast to any derived class. If it were instantiated as a LeadWithImportCheckbox and then returned to your code as Lead, then you can downcast it.
Protip: Check type at runtime with is operator.
There are many ways to do this, but the "right" way pops out because of what you said, here:
For ease of programming (and use), I'm
parsing the text file into a
List object, and using a
DataGridView to display the leads by
setting the DataSource property of the
DataGridView.
What I want to do is add a column to
the grid, called "Import," with a
checkbox that the user can check to
indicate whether or not each lead
should be imported.
Your Lead object stands well on its own, and you want to attach some metadata to it -- you don't want to create another Lead classification (i.e. the LeadWithImportCheckbox class).
So, the best approach in your case is to have a class like so:
public class LeadInfo
{
private Lead lead;
private bool shouldImport;
public LeadInfo(Lead lead)
{
this.lead = lead;
this.ShouldImport = false;
}
public bool ShouldImport
{
get { return shouldImport; }
set { shouldImport = value; }
}
}
This will scale well when you want to add more metadata to your list, like if you want to send yourself email reminders about them every week.
I've seen the correct solution listed so many times I feel like a heel posting it again, but the best way to approach this is to write a wrapper for the Lead object that includes the import flag.
If the properties of the Lead object don't appear in the GridView because you're databinding to the object, then write passthrough properties that mirror the Lead properties on the wrapper object.
The issue is that you want something displayed to the user that isn't an inherent part of the data model. The answer is to wrap the data before presenting it to the user so you can control what they see without changing the underlying model.
If you're concerned that the Lead object will change so many times in the future that changes to the wrapper will be cumbersome, you could look into dynamic code generation based on the Lead object that will automatically generate a wrapper object with the same fields as the Lead object plus the import flag. Though frankly, that's a lot more work than you'll probably need for something as straightforward as this.
As a quick and dirty solution, you can create your 'checkbox' object as a different object that contains an instance of Lead.
public GridLead {
public bool Import { get; set; }
public Lead Lead { get; set; }
}
This way you can easily add more 'grid' properties to this object, while still always retaining a reference to the Lead details without hardcoding property cloning into it.
Recommend you try modifying (upgrading) your imported lead objects.
Try starting with the examples here...
If your Lead class had a copy constructor (e.g. "Lead(Lead otherLead)"), LeadWithImportCheckbox would inherit that and you could just call the base Lead constructor in the LeadWithImportCheckbox constructor - hence no need for LeadWithImportCheckbox to be aware of the details of Lead.

Traversing an arbitrary C# object graph using XPath/applying XSL transforms

I've been looking for a component that would allow me to pass an arbitrary C# object to an XSL transform.
The naive way of doing this is to serialise the object graph using an XmlSerializer; however, if you have a large object graph, this could cause problems as far as performance is concerned. Issues such as circular references, lazy loading, proxies etc may further muddy the waters here.
A better approach is to have some kind of Adapter class that implements IXPathNavigable and XPathNavigator. One such example that I've encountered is the ObjectXPathNavigator from Byte-Force -- however, most of its key documentation is in Russian, and my initial tests seem to indicate that it has a few quirks and idiosyncrasies.
Does anyone know of either (a) any resources (overviews, tutorials, blog posts etc) about this particular in English or (b) any other alternatives that offer the same or similar functionality?
There's a (very) old MSDN article titled XPath Querying Over Objects with ObjectXPathNavigator that implements a similar class (Also called ObjectXPathNavigator, interestingly enough). I used this ages ago to query some data from Visual SourceSafe and build an RSS feed from the changelog, and it worked quite well. However, I didn't do XSLT with it, so I'm not sure if that works or not. Also, note that it was written for Framework 1.0, so you may need to update it for more recent frameoworks. Also, there may be better ways to do this now, but it would give you a starting point (and the article does a nice job of explaining how it works).
Sounds as though the problem you're trying to solve is quite interesting.
At first glance, I'd suggest writing your own implementation of an XPathNavigator descendant - there are only 20-odd methods to write, and none of them have a particularly difficult signature.
A naive implementation using non-cached reflection would be slow(ish) but would work well as a proof of concept and you could make changes to improve performance if/when that became an issue.
However ...
... I think you may run into some difficulties that stem from your approach, not from any implementation detail.
An XML file is (by nature) a simple hierarchy of elements and attributes - there are no loops (aka cycles) in the node graph.
An XPath expression can include the operator "//" which broadly means to search to unlimited depth. (For an exact definition, see section 2.5 of XPath 1.0.)
If you applied such an expression to an object graph with cross references (aka object cycles), then you run the risk of the XPath evaluator going into an infinite loop as it tried to recursively enumerate an effectively infinite graph.
You may be able to work around this issue by somehow keeping track of parent nodes in your XPathNavigator and throwing an exception if a loop is detected, but I'm not sure how viable this will be.
Since the object graph may be cyclic, you cannot possibly make a Tree-based structure out of it. Your best bet is to represent the object graph by it's simplest components: nodes and vectors.
More specifically, make each node (object) an element with a unique ID (perhaps provided by C#'s GetHashCode() method?). References to other objects (vectors) would be handled by referencing the ID of the object.
Example classes (note that I don't know C# so my syntax may be a bit off):
public class SomeType {
public int myInt { get; set; }
}
public class AnotherType {
public string myString { get; set; }
public SomeType mySomeType { get; set; }
}
public class LastType {
public SomeType mySomeType { get; set; }
public AnotherType myAnotherType { get; set; }
}
public class UserTypes{
static void Main()
{
LastType lt = new LastType();
SomeType st = new SomeType();
AnotherType atype = new AnotherType();
st.myInt = 7;
atype.myString = "BOB";
atype.mySomeType = st;
lt.mySomeType = st;
lt.myAnotherType = atype;
string xmlOutput = YourAwesomeFunction(lt);
}
}
Then we would expect the value of xmlOutput to be something like this (note that the ID values chosen are completely synthetic):
<ObjectMap>
<LastType id="0">
<mySomeType idref="1" />
<myAnotherType idref="2" />
</LastType>
<SomeType id="1">
<myInt>7</myInt>
</SomeType>
<AnotherType id="2">
<myString>BOB</myString>
<mySomeType idref="1" />
</AnotherType>
</ObjectMap>
You could try something like this:
http://code.google.com/p/antix-software/wiki/AntixReflectionQuery

Sorting a composite collection

So WPF doesn't support standard sorting or filtering behavior for views of CompositeCollections, so what would be a best practice for solving this problem.
There are two or more object collections of different types. You want to combine them into a single sortable and filterable collection (withing having to manually implement sort or filter).
One of the approaches I've considered is to create a new object collection with only a few core properties, including the ones that I would want the collection sorted on, and an object instance of each type.
class MyCompositeObject
{
enum ObjectType;
DateTime CreatedDate;
string SomeAttribute;
myObjectType1 Obj1;
myObjectType2 Obj2;
{
class MyCompositeObjects : List<MyCompositeObject> { }
And then loop through my two object collections to build the new composite collection. Obviously this is a bit of a brute force method, but it would work. I'd get all the default view sorting and filtering behavior on my new composite object collection, and I'd be able to put a data template on it to display my list items properly depending on which type is actually stored in that composite item.
What suggestions are there for doing this in a more elegant way?
I'm not yet very familiar with WPF but I see this as a question about sorting and filtering List<T> collections.
(withing having to manually implement sort or filter)
Would you reconsider implementing your own sort or filter functions? In my experience it is easy to use. The examples below use an anonymous delegate but you could easily define your own method or a class to implement a complex sort or filter. Such a class could even have properties to configure and change the sort and filter dynamically.
Use List<T>.Sort(Comparison<T> comparison) with your custom compare function:
// Sort according to the value of SomeAttribute
List<MyCompositeObject> myList = ...;
myList.Sort(delegate(MyCompositeObject a, MyCompositeObject b)
{
// return -1 if a < b
// return 0 if a == b
// return 1 if a > b
return a.SomeAttribute.CompareTo(b.SomeAttribute);
};
A similar approach for getting a sub-collection of items from the list.
Use List<T>.FindAll(Predicate<T> match) with your custom filter function:
// Select all objects where myObjectType1 and myObjectType2 are not null
myList.FindAll(delegate(MyCompositeObject a)
{
// return true to include 'a' in the sub-collection
return (a.myObjectType1 != null) && (a.myObjectType2 != null);
}
"Brute force" method you mention is actually ideal solution. Mind you, all objects are in RAM, there is no I/O bottleneck, so you can pretty much sort and filter millions of objects in less than a second on any modern computer.
The most elegant way to work with collections is System.Linq namespace in .NET 3.5
Thanks - I also considered LINQ to
objects, but my concern there is loss
of flexibility for typed data
templates, which I need to display the
objects in my list.
If you can't predict at this moment how people will sort and filter your object collection, then you should look at System.Linq.Expressions namespace to build your lambda expressions on demand during runtime (first you let user to build expression, then compile, run and at the end you use reflection namespace to enumerate through results). It's more tricky to wrap your head around it but invaluable feature, probably (to me definitively) even more ground-breaking feature than LINQ itself.
Update: I found a much more elegant solution:
class MyCompositeObject
{
DateTime CreatedDate;
string SomeAttribute;
Object Obj1;
{
class MyCompositeObjects : List<MyCompositeObject> { }
I found that due to reflection, the specific type stored in Obj1 is resolved at runtime and the type specific DataTemplate is applied as expected!

Categories

Resources