I'm about to build a search page on a website and the search is going to be extensive with a couple of models and with each model having a lot of properties.
Is there a way to do this in a generic way or use reflector as I have seen in some posts? I need some pointers or tips on how to aproach this. Highly appreciate it.
You can use reflection to get the information you need. If you have a type T you can use
typeof(T).GetProperties()
to get all public properties. Same is possible for fields, methods, ... If you need more meta data to generate your search, you can use attributes to annotate the properties (or fields, methods, ...) That's the way I would get started. Further details depend on your exact use case.
Can you give more details?
What is the purpose of your search? Give me the 30 second version so I can understand where you are going with this.
Are you planning on using RegEx and word stemming?
What kinds of values count as matches?
I assume you only want to search properties on the objects/models. Right?
Do want to see every property or only some of them?
What kinds of data is stored in the properties? (string, byte[], enum, etc)
Brainstorming Ideas:
What about searching one the DB server-side instead of in your hydrated objects? It might be faster (at run-time) to leverage your DB than load all of the objects into memory then reflect upon them.
You could also write a method that supports your search within the context of the model itself. You pass in the search rule set as an expression then find the match. If you have some kind of a collection container, the search could be run at that level against all of the objects in the collection.
If you want some reflection code, I wrote something that shows a lot of info about an object via reflection. I wrote this a long while ago (Dec 2009). I'm not sure if it does what you want. Take a look. If it works for you, use it! (Link)
Related
Background:
I have 2 instances of an object of the same type. One object is populated with the configuration of a device I'm connected to, the other object is populated with a version of the configuration that I've stored on my hard drive.
The user can alter either, so I'd like to compare them and present the differences to the user.
Each object contains a number of ViewModel properties, all of which extend ViewModelBase, which are the ones I want to compare.
Question:
Is a better way to do this than what I'm about to propose.
I'm thinking of using Reflection to inspect each property in my objects, and for each that extend ViewModelBase, I'll loop through each of those properties. For any that are different, I'll put the name and value into a list and then present that to the user.
Rather than inventing this wheel, I'm wondering if this is this a problem that's been solved before? Is there a better way for it to be done?
Depending on the amount of properties to be compared, manual checking would be the more efficient option. However, if you have lots of properties or want the check to be dynamic (i.e. you just add new properties and it automagically works), then I think Reflection is the way to go here.
Why not just implement the equals operator for your type?
http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx
Edit: Having read more carefully I see what you're actually asking is what the most efficient way of doing the actual comparison is.
Doing it via reflection saves on code but is slower. Doing it with lots of manual comparions is fairly quick but more code.
If you are fairly determent and lazy in the good way. You can mix benefits of both solutions. With help of tool like cci you can emit method that compares properties. The beauty of this is that your reflection code will be executed on compile time leaving you with strait forward method to execute at runtime. This allows you to change models as you see fit and not worry about comparison code. There is a down side to this and that is learning cci which is quite challenging.
I got two objects from the same class and I need to compare them field by field. The problem is that they have close to hundred fields and it would be helluva work to write that by hand.
Do you know any way to do that the easier way? Reflections in Java could be a solution, but yet it seems to me like a hack. And I seek a C# solution after all.
Two ideas:
Use reflection (it is available in C#) runtime and loop over the fields of the clas comparing them. If you want to be able to exclude certain fields you could do that by creating an attribute class and mark the fields you don't want to compare with that attribute.
Use reflection to loop over the fields in the same way and generate the required comparison code. This way you will have "real" code but won't have to write and maintain it yourself. Attributes can be used to fine-tune the comparison code generated.
The best is to refactor your code, hundred fields is way to mush.
If you can't because is a legacy code find out which attribute make them equals.
If you're lucky, you'll identify one or two properties that are unique for the instance -- especially likely if you class represents a database entity -- and you will only have to compare those unique properties.
Use Regular Expression find and replace. It's a pain when you have to add fields *(removed ones get you a compile error), but you get the benefit of having compiled code.
Really, though, consider splitting the class up. If there's 100 fields, can they be grouped in component classes? 100 members is a lot of mess to have to manage.
I am fairly new to reflection and I would like to know, if possible, how to create an instance of a class then add properties to the class, set those properties, then read them later. I don't have any code as i don't even know how to start going about this. C# or VB is fine.
Thank You
EDIT: (to elaborate)
My system has a dynamic form creator. one of my associates requires that the form data be accessible via web service. My idea was to create a class (based on the dynamic form) add properties to the class (based on the forms fields) set those properties (based on the values input for those fields) then return the class in the web service.
additionally, the web service will be able to set the properties in the class and eventually commit those changes to the db.
If you mean dynamically create a class, then the two options are:
Reflection.Emit - Difficult, Fast to create the class
CodeDom - Less Difficult, Slower to create the class
If you mean create an instance of an existing class, then start with Activator.CreateInstance to create an instance of the object, and then look at the methods on Type such as GetProperty which will return a PropertyInfo that you can call GetValue and SetValue on.
Update: For the scenario you describe, returning dynamic data from a web service, then I'd recommend against this approach as it's hard for you to code, and hard for statically-typed languages to consume. Instead, as suggested in the comments and one of the other answers, some sort of dictionary would likely be a better option.
(Note that when I say return some sort of dictionary, I am speaking figuratively rather than literally, i.e. return something which is conceptually the same as a dictionary such as a list of key-value pairs. I wouldn't recommend directly returning one (even if you're using WCF which does support this) because it's typically better to have full control over the XML you return.)
I know this is being overly simplified by why not just KISS and generate the required Xml to return through the Web Service and then parse the returned Xml to populate the database.
My reasoning is that for the expanded reason you suggest doing this I can see the value or reason for wanting a dynamic class?
The Execution-Time Code Generation chapter of Eric Gunnerson's book (A Programmer's Introduction to C#) has some great information on this topic. See page 14 and onwards in particular. He outlines the two main methods of accomplishing dynamic class/code generation (CodeDOM and the Reflection.Emit namespace). It also discusses the difficulty and performance of the two approaches. Have a read through that, and you ought to find everything you might need.
The real question is, what do you need to use those properties for?
What are gonna be the use cases? Do you need to bind those properties to the UI somehow? Using what kind of technology? (WPF, Windows Forms?)
Is it just that you need to gather a set of key/value pairs at runtime? Then maybe a simple dictionary would do the trick.
Please elaborate if you can on what it is you need, and I'm sure people here can come up with plenty of ways to help you, but it's difficult to give a good answer without more context.
Every time I see a search function, the code behind it is a mess. Several hundreds of lines, spaghetti code, and almost ALWAYS as one huge method. A programming language (Java/C#/PHP/etc) is used to construct one big fat SQL query. Many, many if else's.
There must be more elegant ways to do this than this? Or is this what you get when you use RMDBS instead of a flat data structure?
I'd be willing to learn more about this topic, perhaps even buy a book. /Adam
Use the query object pattern. If you can, also use an ORM, it will make things easier.
The implementation details depend on your platform and architecture, but here are some samples:
http://www.theserverside.com/patterns/thread.tss?thread_id=29319
http://www.lostechies.com/blogs/chad_myers/archive/2008/08/01/query-objects-with-the-repository-pattern.aspx
In my current project we use a simplified version of the query object pattern that mausch mentions. In our case we have a search criteria object that consists of a field and a value, and several such objects can be added to a list. We did have an operator property from the start, but it was never used so we removed it. Whether the criteria are treated as AND or OR depends on the search method that is used (I would say that it is AND in 95% of the cases in that project).
The find methods themselves do not do a lot with this information; they will invoke stored procs in the DB, passing the criteria as parameters. Most of those procs are fairly straight forward, even though we have a couple that does involve some string handling to unpack lists of critera for certain fields.
The code from a caller's perspective might look something like this (the Controller classes wraps repetetive stuff as instantiating a search object with a configurable implementation*, populating it with search criteria and such):
CustomerCollection customers = CustomerController.Find(new SearchCriterion("Name", "<the customer name>"));
If more than one search criterion is needed a collection can be passed instead. Inside the finder function the code will loop over the collection, map the present values to appropriate parameters in an SqlCommand object.
This approach has worked out rather well for us.
*) The "configurable implementation" means that we have created an architecture wher the search objects are defined as abstract classes that merely will define the interface and contain some generic pre- and post validation. The actual search code is implemented in separate decendent classes; which amongst other things allowed us to quickly create a "fake data layer" that could be used for mocking away the database for some of the unit tests.
Have you looked at the Lucene project (http://lucene.apache.org)? Its designed exactly for this purpose. The idea is that you build and then maintain a set of indexes that are then easily searchable. The lifecycle works like this:
Write a bunch of sql statements that index all of the searchable areas of your database
Run them against the full database to create an initial index of your data
Every time the data changes, update these indexes.
The query language is much simpler then, you're queries become much more targeted.
There is a great project in the hibernate tool suite called hibernate search (http://search.hibernate.org) that does the maintenance of your indexes for you if you are using hibernate as your ORM.
I've been tinkering with this thought a bit (since I actually had to implement something like this some time ago) and I've come to the conclusion that there's two ways I'd do it to make it both work and especially maintainable. But before going into those, here's some history first.
1. Why does the problem even exist
Most search functions are based on algorithms and technologies derivated from the ones in databases. SQL was originally developed in the early 1970's (Wikipedia says 1974) and back then programming was a whole another kind of beast than it is today because every byte counted, every extra function call could make the difference between excellent performance and bankruption, code was made by people who thought in Assembly...well you get the point.
The problem is that those technologies originally have mostly been carried over to modern world without changing them (and why should they be changed, don't fix something which isn't broken) which means the old paradigms creep around too. And then there's cases when the original algorithm is misinterpreted for some reason and you end up with what you now have, like slow regular expressions. A bit of underlining here is required though, the technologies themselves aren't bad, it's usually just the legacy paradigms which are!
2. Solutions to the problem
The solution I ended up using was a system which was a mix of builder pattern and query object pattern (linked by mausch already). As an example if I were to make a pragmatic system to build SQL queries, it would look something like this:
SQL.select("column1", "column2")
.from("relation")
.where().valueEquals("column1", "hello")
.and().valueIsLargerThan("column2", 3)
.toSQL();
The obvious downside of this is that the builder pattern has the tendency to be a bit too verbose. Upsides are that the each of the build steps (=methods) are quite small by nature, for example .valueIsLargerThan("a", x) merely may just be return columnName + ">=" + x;. This means they're easily unit-testable and one of the biggest upsides is that they can be generated easily from external sources like XML/whatnot and most notably it's rather easy to create a converter from, say, SQL query to Lucene query (Lucene has automation for this already afaik, this is just an example).
The second one I'd rather use but really avoid is because it's not order-safe (unless you spend a good amount of time creating metadata helper classes) while builders are. It's easier to write an example than to go into more detail what I mean, so:
import static com.org.whatever.SQL.*;
query(select("column1", "column2"),
from("relation"),
where(valueEquals("column1", "hello"),
valueIsLargerThan("column2", 3)));
I do count static imports as a downside but other than that, that looks like something I'd really want to use.
I have an object in C# with lets say 20 properties and it's part of a datacontract. I also have another business entity with similar properties, which I want to populate from the response object. Is there any way to do this other than assigning each property of one object to the corresponding properties of the other?
Yes, take a look at Automapper
MiscUtil has an answer to this (PropertyCopy) that uses Expression (.NET 3.5) and a static field to cache the compiled delegate (so there is negligible cost per invoke):
DestType clone = PropertyCopy<DestType>.CopyFrom(original);
If you are using 2.0, then probably reflection would be your friend. You can use HyperDescriptor to improve the performance if you need.
Reflection is an option if you want to do it in an automated manner, provided the property names are easily mappable between the objects.
Automapper is worth a try, but in the end, I decided it wasn't for me. The big problem with those sorts of tools is you incur a great deal of runtime overhead each and every time a mapping occurs. I asked this same question last week and I ended up rolling my own solution (look at the accepted answer). You're free to modify the source I provided, I make no claims as to it's effectiveness, suitability, performance, you-break-it-you-get-to-keep-the-pieces, etc., but it works well enough for me to create design time object to object mapping.
C# Object Clone Wars might be a good starting point.