I have been spending quite a lot time recently on the different J2EE frameworks (Spring, Hibernate, etc.). The power of most of these frameworks flows from their ability to substitute implementations at runtime, by simply replacing the name of a class in a configuration file. Come to think of it, even the much-maligned JDBC works this way -- you can replace your driver class in the place where you set up your connection pool. Dynamic loading of classes at runtime is what make this possible. Reflection is also used to provide additional flexibility; for example, Spring uses reflection to invoke getter and setter methods on the classes and further abstract away the relationship between them.
I have not worked in .NET, but I think these features must be available there as well. In the earlier days, the only way one could do such things was a) loading a shared library dynamically from a file name supplied at run time (nowhere near as powerful as loading a class) and b) specifying a CLSID or IID in COM (my knowledge of COM is a bit rusty right now, so I am not sure whether this can be done at runtime).