Reflection (Reflection) is. NET, which can be obtained at runtime through reflection. NET, including methods, attributes, events, and constructor. You can also obtain the name, qualifier, and parameters of each member. With reflection, you can be familiar with every type. If you obtain information about the constructor, you can directly create an object, even if the object type is unknown during compilation.
Assembly is an application that reflects reflection. It defines and loads an Assembly, loads modules in the Assembly list, and searches for a type from this Assembly and creates an instance of this type. Simply put, you do not need to write the following in advance when using Assembly in a program:
PersonClass person = new PersonClass ();
Person. Method ();
As long as you know the assembly of the PersonClass class, namespaces and class names can be directly used for reflection. You only need to write as follows:
PersonClass person;
Person =
Person = (PersonClass) (Assembly. load ("assembly "). createInstance ("namespace. class Name ", false, BindingFlags. default, null, args, null, null ));
Person. Method ();
Next we will use a small example to look at the convenience of the Assembly application.
Requirement: There are several file formats with suffixes:. One,. Two,. Three,... there are many types of files that may be added later. The formats of these files are different, that is, the reading method is different. Then, read the file content based on the entered file suffix and path.
Implementation:
This requirement is characterized by different processing based on selection, but it is a result, so you can use a simple factory mode to complete it.
The file to be read has a parent class FileSuper, Which is internally as follows:
Using System;
Using System. Collections. Generic;
Using System. Text;
Namespace reflect
{
Public abstract class FileSuper // obtain the content of files with different extension names
{
Public abstract string GetFileContext (string fileFullPath );
}
}
MyFileOne, MyFileTwo, and MyFileThree are inherited from FileSuper, as follows:
Using System;
Using System. Collections. Generic;
Using System. Text;
Namespace reflect
{
Public class MyFileOne: FileSuper
{
Public override string GetFileContext (string fileFullPath)
{
Return "content of One type file ";
}
}
} Using System;
Using System. Collections. Generic;
Using System. Text;
Namespace reflect
{
Public class MyFileTwo: FileSuper
{
Public override string GetFileContext (string fileFullPath)
{
Return "Two type file content ";
}
}
}
Using System;
Using System. Collections. Generic;
Using System. Text;
Namespace reflect
{
Public class MyFileThree: FileSuper
{
Public override string GetFileContext (string fileFullPath)
{
Return "Three type file content ";
}
}
}
A factory class decides which class to instantiate Based on the Suffix:
Using System;
Using System. Collections. Generic;
Using System. Text;
Namespace reflect
{
Public class OperationFile
{
Static FileSuper fileSuper = null;
Public static string GetStringByFile (string fileFullPath, string extendName)
{
Switch (extendName)
{
Case "One ":
FileSuper = new MyFileOne ();
Break;
Case "Two ":
FileSuper = new MyFileTwo ();
Break;
Case "Three ":
FileSuper = new MyFileThree ();
Break;
}
If (fileSuper! = Null)
{
Return fileSuper. GetFileContext (fileFullPath );
}
Return "no specified type ";
}
}
}
Client call. The result is displayed:
Using System;
Using System. Collections. Generic;
Using System. Text;
Namespace reflect
{
Public class Program
{
Static void Main (string [] args)
{
String fileContext = OperationFile. GetStringByFile ("path", "One ");
Console. WriteLine (fileContext );
Console. ReadLine ();
}
}
}
This solves this requirement. I mentioned the disadvantage of this method in my reading Note 6: The Factory method mode is that it does not conform to the principle of open and closed, so how can we improve it? Besides the factory method mode, we can use Assembly. Before using it, you must first write a class and a configuration file.
First look at the configuration file: MyFile. xml
<? Xml version = "1.0" encoding = "UTF-8"?>
<FileExtendName>
<Extend>
<Name> One </name>
<Class> MyFileOne </class>
</Extend>
<Extend>
<Name> Two </name>
<Class> MyFileTwo </class>
</Extend>
<Extend>
<Name> Three </name>
<Class> MyFileThree </class>
</Extend>
</FileExtendName>
Is the extension name and class name.
The other class that reads the configuration file ExtendNameDataTable.
Using System;
Using System. Collections. Generic;
Using System. Text;
Using System. Data;
Namespace reflect
{
Public class ExtendNameDataTable
{
Private static DataSet extendDataSet;
Public static DataSet ExtendDataSet
{
Get
{
If (extendDataSet = null)
{
ExtendDataSet = new DataSet ();
ExtendDataSet. ReadXml (@ "F: \ MyFile. xml ");
}
Return extendDataSet;
}
}
}
}
After preparing the two, you only need to modify the OperationFile factory class. Use Assembly to automatically load classes based on the configuration file according to the passed extension name and instantiate the class. The modified OperationFile is as follows:
Using System;
Using System. Collections. Generic;
Using System. Text;
Using System. Data;
Using System. Reflection;
Namespace reflect
{
Public class OperationFile
{
Public static string GetStringByFile (string fileFullPath, string extendName)
{
DataRow dr = (DataRow []) ExtendNameDataTable. ExtendDataSet. Tables [0]. Select ("name = '" + extendName + "'") [0];
Object [] args = null;
FileSuper fileSuper;
FileSuper = (FileSuper) (Assembly. Load ("reflect"). CreateInstance (
"Reflect." + dr ["class"]. ToString (), false, BindingFlags. Default, null, args, null, null ));
Return fileSuper. GetFileContext (fileFullPath );
}
}
}
The client call will not change the output result:
As we can see, if a new file structure is available, you only need to write another MyFileFour class inherited from FileSuper; then in MyFile. add the corresponding ing in xml to avoid modifying the case branch of OperationFile, which complies with the open and closed principle.
Of course, Assembly is so easy to use and can not be used in all circumstances. When this happens in a loop, we should use the simple factory mode or factory method mode, because the use of Assembly instantiation in recycling results in performance degradation.