Reflection
is an important mechanism in C#
that allows to get information
about the members
and every member’s type
(class, structure, delegate, interface, enum, etc.) from a program
or assembly
(dll, exe) at runtime
.
Pros
: Reflection improves theflexibility
andextensibility
of the program,reduces the coupling
andimproves the adaptability
. It allows programs to create and control objects of any class without hard-coding the target class in advance.
Cons
: Reflection is veryslow
, and make the internal logic of the program morecomplex
, and hard toread
andmaintain
.
The System.Type class plays a central role
in reflection. It represents the instance of the target Class
, and provides all the methods of getting the type
information from the target class.
typeof()
operation: Type t = typeof(string);
GetType()
method: string s = "grayworm";
Type t = s.GetType();
Type.Name:
Get the Type’s nameFullName:
Get full names of the Type(include namespace)Namespace:
Get the NameSpace nameIsAbstract:
Get a bool shows if this type is an abstract typeIsArray:
Get a bool shows if this type is an arrayIsClass:
Get a bool shows if this type is a classIsEnum:
Get a bool shows if this type is an enumIsInterface:
Get a bool shows if this type is an interfaceIsPublic:
Get a bool shows if this type is publicIsSealed:
Get a bool shows if this type is sealedIsValueType:
Get a bool shows if this type is value type, if not then it’s reference typeAfter
Getting the Type
of the Object through the following code:
// Create a new instance of the TargetClass
TargetClass tc = new TargetClass();
// Get the type of TargetClass
Type t = tc.GetType();
Then it will be able to call the
Type
class’smethods
to get the information.
GetField(), GetFields():
Return a FieldInfo
Type, for getting the class Member variables’ information. // Get the Fields from the TargetClass
FieldInfo[] fis = t.GetFields();
foreach (FieldInfo fi in fis)
{
Debug.Log(fi.Name);
}
GetMethod(), GetMethods():
Return a MethodInfo
Type, for getting the methods’ information of the class. // Get the Methods from the TargetClass
MethodInfo[] mis = t.GetMethods();
foreach (MethodInfo mi in mis)
{
Debug.Log(mi.ReturnType + " " + mi.Name);
}
GetProperty(), GetProperties():
Return a PropertyInfo
Type, for getting the Properties’ information of the class. // Get the Properties from the TargetClass
PropertyInfo[] pis = t.GetProperties();
foreach (PropertyInfo pi in pis)
{
Debug.Log(pi.Name);
}
GetConstructor(), GetConstructors():
Return a ConstructorInfo
Type, used for get the class’s Constructors’s information. // Get all the Constructors of the TargetClass
ConstructorInfo[] constructorInfos = t.GetConstructors();
foreach (ConstructorInfo info in constructorInfos)
{
// Get all the parameters of the constructor
ParameterInfo[] parameterInfos = info.GetParameters();
foreach (ParameterInfo pi in parameterInfos)
{
Debug.Log(pi.ParameterType.ToString() + " " + pi.Name + ",");
}
}
GetEvent(), GetEvents():
Return a EventInfo
Type, for getting the class’s event’s information. // Get the Events from the TargetClass
EventInfo[] mis = t.GetEvents();
foreach (EventInfo mi in mis)
{
Debug.Log(mi.EventHandlerType + " " + mi.Name);
}
GetMember(), GetMembers():
Return a MemberInfo
Type, for getting all the members’s information of this class. // Get the Members from the TargetClass
MemberInfo[] mis = t.GetMembers();
foreach (MethodInfo mi in mis)
{
Debug.Log(mi.ReturnType + " " + mi.Name);
}
For calling these member, using Type.InvokeMember()
, or other class’s(such as FieldInfo, EvenetInfo, PropertyInfo, etc.) Invoke()
functions.
BindingFlags
is to Specify flags that control binding and the way in which the search for members and types is conducted by reflection.
Some Common BindingFlags:
BindingFlags.IgnoreCase:
Ignore the Case of the member nameBindingFlags.DeclaredOnly:
Only Accept the members declared in this class not include inherited memebers.BindingFlags.Instance:
Only Accept the Instance membersBindingFlags.Static:
Only Accept the Static membersBindingFlags.Public:
Only accept the public membersBindingFlags.NonPublic:
Only accept the nonpublic membersCode example:
// Here `|` needs to satisify all of these three Flags members will be get fis = typeof(TargetClass).GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
Assembly Class can get Assembly's information
, dynamically loads
the Assembly, and finds type
information in the Assembly and creates Instance
of that type.
Assembly ass = Assembly.Load("ClassLibrary");
Type t = ass.GetType("ClassLibrary.NewClass");
object o = Activator.CreateInstance(t);
MethodInfo mi = t.GetMethod("show");
mi.Invoke(o, null);
Assembly assembly = Assembly.LoadFrom("xxx.dll's path");
Type[] aa = a.GetTypes();
foreach(Type t in aa)
{
if(t.FullName == "a.b.c")
{
object o = Activator.CreateInstance(t);
}
}
When we are creating the instance in C# we normally will create the object statically.
For example, we have three classes, ClassA, ClassB, ClassC, each of them has a function.
public class ClassA
{
public void FunctionA()
{
Debug.Log("Run Function A");
}
}
public class ClassB
{
public void FunctionB()
{
Debug.Log("Run Function B");
}
}
public class ClassC
{
public void FunctionC()
{
Debug.Log("Run Function C");
}
}
When we want to create certain object through code, we have to use switch case or if statement to make decision and create instance one by one, which is staticly create instance.
public class ReflectionExample : MonoBehaviour
{
private void Start()
{
CreateObject("A");
CreateObject("B");
CreateObject("C");
}
public static void CreateObject(string className)
{
switch (className)
{
case "A":
ClassA a = new ClassA();
a.FunctionA();
break;
case "B":
ClassB b = new ClassB();
b.FunctionB();
break;
case "C":
ClassC c= new ClassC();
c.FunctionC();
break;
default:
break;
}
}
}
However, We can use
Reflection
to create ObjectDynamicly
based on the type’s name:
namespace ReflectionDemo
{
public class ClassA
{
public void FunctionA()
{
Debug.Log("Run Function A");
}
}
public class ClassB
{
public void FunctionB()
{
Debug.Log("Run Function B");
}
}
public class ClassC
{
public void FunctionC()
{
Debug.Log("Run Function C");
}
}
public class ReflectionExample01 : MonoBehaviour
{
private void Start()
{
DynamicCreateObject("A");
DynamicCreateObject("B");
DynamicCreateObject("C");
}
public static void DynamicCreateObject(string className)
{
var fullPathName = "ReflectionDemo.Class" + className;
Type type = Type.GetType(fullPathName);
var obj = Activator.CreateInstance(type);
var method = obj.GetType().GetMethod("Function" + className);
if (method != null)
{
method.Invoke(obj, null);
}
}
}
}
End –Cheng Gu