当前位置:网站首页>. Net basic knowledge quick pass 10
. Net basic knowledge quick pass 10
2022-06-09 12:32:00 【Phil Arist】
1 The basic principle of reflection
Reflection is a Dynamically analyze assemblies 、 modular 、 Mechanisms for target objects such as types and fields , Its implementation relies on metadata .
Metadata , It's the data that describes the data .
stay CLR in , Metadata is a description system of everything defined or referenced by a module .
2.NET How to implement reflection in
stay .NET in , It provides us with a wealth of types that can be used to implement reflection , Most of these types are defined in System.Reflection Under the namespace , for example Assembly、Module etc. . Utilize these types , We can easily dynamically load assemblies 、 modular 、 type 、 Elements such as methods and fields .
Let's take a look at an example , The first is to create an assembly SimpleAssembly, One of the classes is SimpleClass:
[Serializable]
public class SimpleClass
{
private String _MyString;
public SimpleClass(String mystring)
{
_MyString = mystring;
}
public override string ToString()
{
return _MyString;
}
static void Main(string[] args)
{
Console.WriteLine(" Simple assembly ");
Console.Read();
}
}
The second is to analyze the modules in the assembly , Use reflection on assemblies, respectively 、 Modules and classes :
public class AnalyseHelper
{
/// <summary>
/// Parse assembly
/// </summary>
public static void AnalyzeAssembly(Assembly assembly)
{
Console.WriteLine(" Assembly name :" + assembly.FullName);
Console.WriteLine(" Assembly location :" + assembly.Location);
Console.WriteLine(" Whether the assembly is in GAC in :" +
assembly.GlobalAssemblyCache.ToString());
Console.WriteLine(" Contains the module name of the assembly " +
assembly.ManifestModule.Name);
Console.WriteLine(" Required to run the assembly CLR edition :" +
assembly.ImageRuntimeVersion);
Console.WriteLine(" Now start analyzing the modules in the assembly ");
Module[] modules = assembly.GetModules();
foreach (Module module in modules)
{
AnalyzeModule(module);
}
}
/// <summary>
/// Analysis module
/// </summary>
public static void AnalyzeModule(Module module)
{
Console.WriteLine(" Module name :" + module.Name);
Console.WriteLine(" Modular UUID:" + module.ModuleVersionId);
Console.WriteLine(" Start analyzing the types under the module ");
Type[] types = module.GetTypes();
foreach (Type type in types)
{
AnalyzeType(type);
}
}
/// <summary>
/// Analysis type
/// </summary>
public static void AnalyzeType(Type type)
{
Console.WriteLine(" Type name :" + type.Name);
Console.WriteLine(" The category of type is :" + type.Attributes);
if (type.BaseType != null)
Console.WriteLine(" The base class of type is :" + type.BaseType.Name);
Console.WriteLine(" Type of GUID yes :" + type.GUID);
// Set type members of interest
BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
// Analyze members
FieldInfo[] fields = type.GetFields(flags);
if (fields.Length > 0)
{
//Console.WriteLine(" Start analyzing members of type ");
foreach (FieldInfo field in fields)
{
// Analyze members
}
}
// Analyze the included methods
MethodInfo[] methods = type.GetMethods(flags);
if (methods.Length > 0)
{
//Console.WriteLine(" Start analyzing methods of types ");
foreach (MethodInfo method in methods)
{
// Analysis method
}
}
// Analysis properties
PropertyInfo[] properties = type.GetProperties(flags);
if (properties.Length > 0)
{
//Console.WriteLine(" Start analyzing properties of type ");
foreach (PropertyInfo property in properties)
{
// Analysis properties
}
}
}
}Finally, write an entry method to try to analyze a specific assembly :
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public class Program
{
public static void Main(string[] args)
{
Assembly assembly = Assembly.LoadFrom(@"..\..\..\SimpleAssembly\bin\Debug\SimpleAssembly.exe");
AnalyseHelper.AnalyzeAssembly(assembly);
// Create an object of type in an assembly
Console.WriteLine(" Using reflection to create objects ");
string[] paras = { " Test the reflection effect " };
object obj = assembly.CreateInstance(assembly.GetModules()[0].GetTypes()[0].ToString(), true, BindingFlags.CreateInstance, null, paras, null, null);
Console.WriteLine(obj);
Console.ReadKey();
}
}The code above follows Assembly -> modular -> type Three levels of order to dynamically analyze an assembly , Of course, you can continue to recurse the members inside the type , Finally through CreateInstance Method to dynamically create a type , These are the functions that reflection is often used to accomplish , The execution result is shown in the figure below :

3 How to use reflection to implement factory mode
Factory pattern is a common design pattern , The basic idea is to use different factory types to build components of different products . for example , When we were building a room , Windows may be required 、 roof 、 door 、 roof beam 、 Columns and other parts . Some houses need many pillars , And some rooms don't need windows . Under such a demand , You can use factory mode .
(1) The traditional realization of factory mode and its disadvantages
The following figure shows the architecture of the traditional factory model designed for the house :

The design idea of the above figure is :
① The user tells the factory manager which product parts are needed ;
② The factory manager analyzes the incoming information from users , Generate appropriate type objects that implement the factory interface ;
③ Through the factory to produce the corresponding products , Return to the user a type object that implements the product interface ;
Through the above ideas , The implementation code is as follows :
① The first is to define the factory interface , Enumeration of product interfaces and product types
/// <summary>
/// Parts of house products
/// </summary>
public enum RoomParts
{
Roof,
Window,
Pillar
}
/// <summary>
/// Factory interface
/// </summary>
public interface IFactory
{
IProduct Produce();
}
/// <summary>
/// Product interface
/// </summary>
public interface IProduct
{
string GetName();
}② The second is the product class that implements the product interface : The window 、 Roofs and columns
/// <summary>
/// roof
/// </summary>
public class Roof : IProduct
{
// Implementation interface , Return product name
public string GetName()
{
return " roof ";
}
}
/// <summary>
/// The window
/// </summary>
public class Window : IProduct
{
// Implementation interface , Return product name
public string GetName()
{
return " The window ";
}
}
/// <summary>
/// column
/// </summary>
public class Pillar : IProduct
{
// Implementation interface , Return product name
public string GetName()
{
return " column ";
}
}③ Then there is the factory class that implements the factory interface : The implementation interface returns a specific product object
/// <summary>
/// Roof factory
/// </summary>
public class RoofFactory : IFactory
{
// Implementation interface , Return a product object
public IProduct Produce()
{
return new Roof();
}
}
/// <summary>
/// Window factory
/// </summary>
public class WindowFactory : IFactory
{
// Implementation interface , Return a product object
public IProduct Produce()
{
return new Window();
}
}
/// <summary>
/// Column factory
/// </summary>
public class PillarFactory : IFactory
{
// Implementation interface , Return a product object
public IProduct Produce()
{
return new Pillar();
}
}④ Finally, factory management : Organize many products and factories
/// <summary>
/// Plant managers
/// </summary>
public class FactoryManager
{
public static IProduct GetProduct(RoomParts part)
{
IFactory factory = null;
// Disadvantages of the traditional factory mode : Tight coupling between factory management class and factory class family
switch (part)
{
case RoomParts.Roof:
factory = new RoofFactory();
break;
case RoomParts.Window:
factory = new WindowFactory();
break;
case RoomParts.Pillar:
factory = new PillarFactory();
break;
default:
return null;
}
// Use the factory to produce products
IProduct product = factory.Produce();
Console.WriteLine(" Produced a product :{0}", product.GetName());
return product;
}
}According to international practice , Let's implement an entry method to test :
public class Customer
{
public static void Main(string[] args)
{
// Obtain different product parts as required
IProduct window = FactoryManager.GetProduct(RoomParts.Window);
Console.WriteLine(" I got it {0}",window.GetName());
IProduct roof = FactoryManager.GetProduct(RoomParts.Roof);
Console.WriteLine(" I got it {0}", roof.GetName());
IProduct pillar = FactoryManager.GetProduct(RoomParts.Pillar);
Console.WriteLine(" I got it {0}", pillar.GetName());
Console.ReadKey();
}
}stay Customer Class , We have obtained different product parts according to different part types through factory management , The operation result is shown in the figure below :

When a new product — When the floor needs to be added , What we need to change is : Add part enumeration record 、 Add factory class for floor 、 Add a new flooring product class , Modify the factory management class ( stay switch Add a case sentence ), The advantage of this design is that no matter what part is added , Product users don't need to care about internal changes , As always, you can use the factory management class to get the desired parts , The disadvantages are as follows :
① Factory management class and factory class family are coupled ;
② Each time you add a new part, you need to add a pair of factory classes and product classes , There will be more and more types ;
(2) Implementation of reflection based factory pattern
Using reflection mechanism can realize more flexible factory pattern , This is reflected in the use of reflection to dynamically know which components a product is composed of , Instead of using a switch Statement to find the right factory one by one .
① product 、 Enumeration is consistent with the above , The main change here is the addition of two custom features , These two features will be attached to the product type and product interface respectively :
/// <summary>
/// This feature is used to attach to the product type
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class ProductAttribute : Attribute
{
// Annotate members of the part
private RoomParts myRoomPart;
public ProductAttribute(RoomParts part)
{
myRoomPart = part;
}
public RoomParts RoomPart
{
get
{
return myRoomPart;
}
}
}
/// <summary>
/// This feature is used to attach to the product interface type
/// </summary>
[AttributeUsage(AttributeTargets.Interface)]
public class ProductListAttribute : Attribute
{
// Product type collection
private Type[] myList;
public ProductListAttribute(Type[] products)
{
myList = products;
}
public Type[] ProductList
{
get
{
return myList;
}
}
}② The following is the definition of product interface and product class family , The product interface uses ProductListAttribute characteristic , And every product uses ProductAttribute characteristic :
/// <summary>
/// Product interface
/// </summary>
[ProductList(new Type[] { typeof(Roof), typeof(Window), typeof(Pillar) })]
public interface IProduct
{
string GetName();
}
/// <summary>
/// roof
/// </summary>
[Product(RoomParts.Roof)]
public class Roof : IProduct
{
// Implementation interface , Return product name
public string GetName()
{
return " The Little Swan roof ";
}
}
/// <summary>
/// The window
/// </summary>
[Product(RoomParts.Window)]
public class Window : IProduct
{
// Implementation interface , Return product name
public string GetName()
{
return " Shuanghui window ";
}
}
/// <summary>
/// column
/// </summary>
[Product(RoomParts.Pillar)]
public class Pillar : IProduct
{
// Implementation interface , Return product name
public string GetName()
{
return " Millet pillar ";
}
}③ The following is the modified factory class , Due to the use of reflection properties , Here one factory type can produce all the products :
/// <summary>
/// Factory
/// </summary>
public class Factory
{
public IProduct Produce(RoomParts part)
{
// From... By reflection IProduct Interface to get a list of all products
ProductListAttribute attr = (ProductListAttribute)Attribute.GetCustomAttribute(typeof(IProduct), typeof(ProductListAttribute));
// Traverse all implementation product part types
foreach (var type in attr.ProductList)
{
// Use reflection to find its properties
ProductAttribute pa = (ProductAttribute)Attribute.GetCustomAttribute(type, typeof(ProductAttribute));
// Determine whether it is a required part
if(pa.RoomPart == part)
{
// Use reflection to dynamically create instances of product part types
object product = Assembly.GetExecutingAssembly().CreateInstance(type.FullName);
return product as IProduct;
}
}
return null;
}
}④ Finally, the modified factory management class , The core has only three lines of code :
/// <summary>
/// Plant managers
/// </summary>
public class FactoryManager
{
public static IProduct GetProduct(RoomParts part)
{
// There is only one factory
Factory factory = new Factory();
IProduct product = factory.Produce(part);
Console.WriteLine(" Produced a product :{0}", product.GetName());
return product;
}
}The main changes in the above code are two points :
First, the factory management class no longer needs to find different factories according to different parts , Because only one factory is responsible for handling all product parts ;
The second is that the product type and product interface apply two user-defined features , To facilitate factory reflection .ProductAttribute Attached to the product category , It indicates which product part the current type represents . and ProductListAttribute Is attached to the product interface , It is convenient to know how many product parts there are .
When you need to add a new floor product part type , What we need to do is : Add part enumeration record , Add a type that represents the floor , Modification added in IProduct Property initialization parameters on ( Add floor type ), You can see that the caller 、 Both the factory management class and the factory no longer need to make changes to the newly added parts , The program only needs to add the necessary types and enumeration records .
Of course , This design also has some defects : Reflection is relatively inefficient , When there are relatively many product parts , Every time a product is produced, reflection traversal is required, which is a very time-consuming work .
End summary
This paper summarizes and reviews .NET Reflection of (Reflection) Relevant important knowledge points , The next one will summarize .NET Medium characteristics (Attribute) Relevant important knowledge points , Welcome to continue to pay attention !
边栏推荐
- .NET基础知识快速通关10
- SIGIR 2022 | CMI:结合对比学习和多兴趣挖掘的微视频推荐
- curator - 节点类型
- MySQL 乐观锁、悲观锁、多粒度锁
- 09 | the fourth step: the construction and delivery of the middle office
- 08 | middle stage landing step 3: middle stage planning and design
- [reprint] understand G1 garbage collector
- 匿名內部類與局部變量
- 13.<tag-二叉树和BST基础>lt.450. 删除二叉搜索树中的节点 dbc
- Excel | App_ Error in workbookactive cannot set the installed property of class addin
猜你喜欢

7.<tag-回溯和子集问题>lt.70.子集 + lt.90.子集 II

Range method returns the object conversion method

Chaiyunpeng: Cultivation of innovation ability is crucial | interview with oceanbase database competition

Error in Library (patroon): there is no program package named 'patroon'
Play with Web3: create your own erc-721 (NFT)

8. < tag backtracking and full arrangement > lt.46 Full Permutation + lt.47 Full arrangement II

9.<tag-回溯和同层内去重的组合问题>lt.491. 递增子序列

勤于奋国外LEAD赚钱,谈任务的重要性

.NET基础知识快速通关7

Origin 2022b | 更新及安装 | 中英文切换
随机推荐
10.<tag-二叉树和BST基础>lt.700. 二叉搜索树中的搜索 + lt.98. 验证二叉搜索树 + lt.530. 二叉搜索树的最小绝对差(同lt.783)
Tag greedy - brush questions to prepare knowledge - greedy problem solving methods + lt.455 Distribute cookies + lt.376 Wobble sequence
Endnote | 如何快速分享文献给别人(包含题录+备注+pdf文件)| endnote保存备份
【转载】搞懂G1垃圾收集器
Anonymous inner classes and local variables
06 | the first step of China Taiwan landing: enterprise strategy decomposition and current situation research (Discovery)
ThreadPoolExecutor 从精通到入门
Composition maximum area
.NET基础知识快速通关8
What are the deadlock troubleshooting tools?
Rédaction de documents scientifiques
11.<tag-二叉树和BST基础>lt.501. 二叉搜索树中的众数
直播预告|数据库沙龙—【开源生态专场】
LR11安装报错:此计算机上缺少vc2005_sp1_with_atl_fix_redist,请安装所有缺少的必要组件,然后重新运行此安装。
curator - 节点类型
Excel | App_WorkbookActive中存在错误不能设置类 Addin 的Installed属性
『忘了再学』Shell基础 — 28、AWK中条件表达式说明
Gson、FastJson、Jackson 序列化区别
Will investment and wealth management products lose the principal?
Nanny tutorial: how to become a contributor to Apache linkis documents