- It helps to access the metadata for types within an assembly, including constructs such as the full type name, member names.
- It allows to dynamically invoke a type’s member at runtime using the metadata.
- It lets developers to enumerate through all the types within an assembly and search for those that match certain criteria.
- Reflection has the following uses:
- It allows view attribute information at runtime.
- It allows examining various types in an assembly and instantiate these types.
- It allows late binding to methods and properties.
- It allows creating new types at runtime and then performs some tasks using those types.
- There are some provisions for reflecting on generic types.
- Runtime reflection on generics determines whether a class or method contains a generic type, and any type parameters or arguments it may include.
Load Assembly
- If you call
Assembly.Load()
multiple times, the runtime will load the assembly only once.
- If you want to reload the assembly you would have to restart the application.
var typeAssembly = Assembly.GetAssembly(typeof(IMyInterface));
var callingAssembly = Assembly.GetCallingAssembly();
var entryAssembly = Assembly.GetEntryAssembly();
var executingAssembly = Assembly.GetExecutingAssembly();
var pluginAssembly = Assembly.Load("AssemblyName");
// Must use fully qualified name (including namespace) and cast to the target object:
var newInstanceByName = pluginAssembly.CreateInstance("MyNameSpace.MyClassName");
var interfaces = pluginAssembly.GetTypes()
.Where(x => typeof(IMyInterface).IsAssignableFrom(x) && !x.IsInterface);
foreach (Type interfaceType in interfaces)
{
var newInstance = Activator.CreateInstance(interfaceType) as IMyInterface;
newInstance.Action();
}
Accessing Metadata Using System.Type
- Reflection can also be used to inspect the value of a property or a field on one object instance.
FieldInfo[] fields = myObject.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (var field in fields)
if (field.FieldType == typeof(int))
Console.WriteLine(field.GetValue(myObject));
- Reflection can also be used to execute a method on a type.
int myNumber = 42;
MethodInfo compareToMethod = myNumber.GetType().GetMethod("CompareTo", new Type[] { typeof(int) });
int result = (int)compareToMethod.Invoke(myNumber, new object[] { 41 });
- The
GetMethods()
call does not return extension methods.
- They are available only as static members on the type.
Member Invocation
- You can take the metadata and dynamically invoke the members it references.
PropertyInfo property = myObject.GetType().GetProperty("MyProperty",
BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
if (property != null)
{
if (property.PropertyType == typeof(bool))
property.SetValue(myObject, true, null); // Last parameters for indexers
else if (property.PropertyType == typeof(string))
property.SetValue(myObject, "MyValue", null);
Console.WriteLine(property.GetValue(myObject, "MyValue"));
}
Working with Generics
- You can determine whether a class or method contains generic parameters by querying the
ContainsGenericParameters()
.
- You can get a list of generic arguments, or type parameters, from a generic class by calling the
GetGenericArguments()
.
- The result is an array of
Type
instances that corresponds to the order in which they are declared in the generic class.
Type type = typeof(Nullable<>);
var hasGenericParameters = type.ContainsGenericParameters;
var isGenericType = type.IsGenericType;
Type[] genericArgumens = type.GetGenericArguments();