I have recently made the transition from a Java web developer to a C# application developer doing mostly WPF applications. I used to use Spring MVC with Java, where a lot of the code structure was preempted and setup for me. Since I have made the transition to WPF, my applications are reliant on my ability to setup reusable, decoupled code.
I have been trying to improve my skills with certain areas 开发者_如何学Cof design including Generics,Design Patterns and Reflection.
I am well aware of what all these are and for Generics and Design patterns, I am fairly well at applying what I consider best practices(although this is up in the air).
What I am not too familiar with is reflection. I know what reflection is, and I know how to do it to do tasks such as dynamic assembly loading,method and class invocation,etc.
What I do not understand is examples how this might be able to help me.
I constantly hear how reflection can be really helpful if you know how to use it. When I try to research the topic, I only find tutorials and reference of how to do it, instead of the good that it can be used for.
My question is what can I look to as a WPF Developer in using reflection for that will help me, and/or is there a place, or reference that can give me more then just the syntax of using reflection, but also real world examples and/or best practices?
Reflection is a powerful API. At its basic level, reflection allows you to:
- Inspect the types contained in an assembly
- Inspect the members of a given type, including metadata (via attributes)
- Dynamically invoke these members
If you're using the binding mechanism within WPF to bind to normal business objects, then you're already using reflection. The binding API, after looking for more formal binding mechanisms (inheriting from DependencyObject
, having a custom type descriptor, etc.), will use reflection to get and set the values of properties on your business object (or ViewModel).
For example, say you have this class
public class Customer { public string Name { get; set; } }
And your WPF control (view) binds to a collection of these Customer
objects, and has a label control that binds to the Name
property. All of this is defined in XAML, but at runtime the code would look something like this:
var value = dataObject.GetType().GetProperty("Name").GetValue(dataObject, null);
This would obtain the value from the bound object--without knowing anything about its type--and allow the control to display it in the appropriate fashion. Likewise:
dataObject.GetType().GetProperty("Name").SetValue(dataObject, "Bob", null);
Would set the value of the property on that object to "Bob"
, again without knowing anything about its type.
As for how it can help you directly, use cases for this are comparatively rare. If you find yourself in a position to need to use reflection in order to accomplish what you need, you may want to consider refactoring the code; it's always better (in a statically-typed language like C#) to go with code that follows static typing versus using dynamic invocation via reflection. While metadata inspection is fairly cheap, it takes a lot more processing to invoke a member by reflection than it does through ordinary means.
The short answer is, honestly, if you're asking how it can help you, it's best to assume that--for now--it can't.
Reflection can be used for things like:
- ORM (object relational mapper): mapping properties of an object to columns in database table
- Model Binding: Mapping data posted from a web form to properties of an object
- Copying: mapping business objects to DTOs
- Serializing: mapping objects to and from json or xml
- MVC framework: inspecting urls and creating controllers objects based on a naming convention
- Validation: Inspecting objects for Attributes and enforcing validation rules
Example:
public class Customer : Entity
{
[Required]
public string Name { get; set; }
}
And then something else can look for those attributes, like a validator:
public class Validator
{
public ValidationResult Validate(Entity entity)
{
// use reflection to find validation attributes and enforce them
}
}
Reflection is a bit like anonymous methods: It's really hard to see where it's useful until you see the first use case; after that, it's usually easier to figure out.
Here's an actual example from code I wrote about a year and a half ago. For a student project at my university, we were writing a bot in C#, for the purpose of playing Texas Hold 'em. We also wrote an event-based engine which handled the game itself, and included network support to allow both humans and computers to join in from any number of different machines. To allow us to see what was going on, we wrote a separate GUI application which was used to start, join, and participate in games. All players would get added through this application, bots and humans alike.
We implemented our bot to act based on a model, but as we progressed through the project, we made changes to that model, essentially creating different versions of that bot. In our system, we had one class per version of our model.
Once you have different versions, it's nice to be able to compare them against each other to see if your changes have any effect. To do that, we tagged each of our computer player classes with a custom attribute, which we called CPUAttribute
.
That's where reflection came into play: on startup, our GUI would use reflection look at the appropriate assembly and find all of the types we had tagged. Those types would then get added to a dropdown box, and reflection was used to instantiate the selected type when you created the player.
Reflection is the process by which a computer program can observe (do type introspection) and modify its own structure and behavior at runtime
Reflection can be used for observing and/or modifying program execution at runtime. A reflection-oriented program component can monitor the execution of an enclosure of code and can modify itself according to a desired goal related to that enclosure. This is typically accomplished by dynamically assigning program code at runtime.
Example:
//Without reflection
Foo foo = new Foo();
foo.Hello();
//With reflection
object foo = Activator.CreateInstance(null, "Foo");
foo.GetType().GetMethod("Hello").Invoke(foo, null);
Reflection can also be used to adapt a given program to different situations dynamically. For example, consider an application that uses two different classes X and Y interchangeably to perform similar operations. Without reflection-oriented programming, the application might be hard-coded to call method names of class X and class Y. However, using the reflection-oriented programming paradigm, the application could be designed and written to utilize reflection in order to invoke methods in classes X and Y without hard-coding method names. Reflection-oriented programming almost always requires additional knowledge, framework, relational mapping, and object relevance in order to take advantage of more generic code execution. Hard-coding can be avoided to the extent that reflection-oriented programming is used.
Source: Wikipedia
Considered looking MSDN docs.. they have extensive information and example on this topic.
However remember that after Obfuscation sometimes reflection doesn't work.
Reflection is useful for library code, that cannot possibly know about the actual types. A good example is the WPF you mention; how do you think it resolved strings in xaml to properties? And the data-binding strigs inside the xaml?
Classic examples:
- data-binding
- serialization
- ORM - database <===> classes
- IDE / design tooling / editors
- metaprogramming
Your WPF use uses at least 3 of those; probably 4 if you were using a database
You should generally avoid too much reflection in application code; working to interfaces for your domain entities would be preferred.
I can give you a example here. Assume that you have form with all the employee details. Assume that you have a employe class object will all the properties filled.
In this case when you use reflection there is no need to access each and every text box and set the value to the text box , you can write a common method which take a generic employee object and fill in the complete form.
This is where i used reflection.
I even used reflection once to clone a object, i don't know how many properties a particular class file has , its determined at the runtime , so i used reflection to copy all the properties its kind of clonig..
please let me know if you have more doubts.
The best approach in my opinion would be to solve a problem that requires reflection to solve - (fortunately) most problems actually do not require the use of reflection at all, but when they do it does come in handy.
The most recent problem I had to solve using reflection was a custom XMLSerializer/Deserializer where I I had some string type annotation and a string value and was using reflection to re-create and instance of the type (or list of types) from the specified string value at runtime. This required
Activator.CreateInstance()
to create the instance of a generic list of the type- Reflection and use of TypeConverter to create an instance of the primitive type
- Reflection and use of
MethodInfo
to add the primitive type to the list using a generic method at runtime.
Look for a problem in a space that you have otherwise well covered that does require reflection, and then just go for it- learning by doing!
If you know everything at compile time then you don't necessarily ever need to use reflection. Like others mentioned it can be useful to automate building UI, serialization, other code that would otherwise just be boilerplate code that does the same thing over and over for multiple fields in a class.
I have used it in cases where you have to load a dynamically generated plugin dll at runtime. Then you can query the assembly for Types deriving from a particular base class and instantiate and then use the type from the plugin dll.
Another way to use (abuse?) reflection is to bypass encapsulation and set a private field in another object when you know the name of the field, although if you are doing this you have to seriously question if its worth doing.
精彩评论