1. When using reflection, reflection can bypass classes or attributes modified by secure access levels (private, protected) to obtain the required information.
2. Reflection of generics: You can use the attribute Type.ContainsGenericParameters to determine whether a class or method contains generic arguments that have not yet been set, and the attribute Type.IsGenericType represents whether or not it is a generic type.
3. Attribute: Attributes can be used to modify classes and interfaces. Structures, enumerations, delegates, events, attributes, fields, methods, constructors, indexers, parameters, type parameters, return values, assemblies, modules, there are two grammars for using features, which can be multiple "[feature types]" or "[feature types, feature types]. For most of the constructs listed above, you can use the above grammar tags, but this grammar is not suitable for "return values, assemblies, modules".
(1) Assembly, [assembly: property name].
(2) Module, [module: feature name].
(3) Return value, [return: property name].
4. Most features are modified only for specific constructs. To avoid inappropriate use of features, we can use the Attribute Usage Attribute (Attribute Targets. xxx) feature class to restrict tagging features.
5. Named parameters: For example, [Attribute Targets. Class, AllowMultiple = true], the syntax is different from the constructor initialization syntax, because the Attribute UsageAttribute class does not contain a constructor with two parameters. Although C#4.0 supports named parameters, it is also the parameter required to specify the method itself. Named parameters are used to set specific common attributes and fields in feature constructor calls. Even if the constructor does not contain corresponding parameters, named parameters are optional, but they allow additional instance data of the feature to be set without providing a corresponding constructor parameter.
6. Serializable: System.Runtime,Serialization.SerializationInfo objects are essentially a collection of name / value pairs. SerializationInfo objects are used when implementing custom serialization (the ISerializable interface needs to be implemented).
7. Dynamic programming: One of the key functions of reflection is to dynamically find and invoke a particular type of member, which requires the identification of member names or other features at execution time. The new dynamic programming-Dynamic in C 4.0 provides a simpler way to invoke members by reflection, but the limitation of this technology is that members and signatures need to be known at compile time. If the member is not actually found at execution time, the call raises a RuntimeBinderException exception. You can see the UseDynamic.Test() code.
8. Dynamics: Basically, Dynamics is an Object, where any object can be implicitly converted to Dynamics, and Dynamics can be explicitly converted to other objects, so Dynamics behaves like Objects, similar to Objects, and even returns null (default(dynamic) for its default value. Dynamic's special dynamic behavior only occurs when invoked, which is the key to distinguishing it from Object. Any member call to dynamic returns to the dynamic type, but if GetType() is executed on Dynamic, it returns to the compiled type (that is, the type finally assigned to the dynamic variable).
9. Implementing custom dynamic objects: The key to defining custom dynamic types is to implement the System.Dynamic.IDynamic MetaObjectProvider interface, but it does not need to be implemented from scratch. Instead, the first solution is to inherit from the System.Dynamic.DynamicObject class and rewrite the corresponding methods. The DynamicObject class has implemented the IDynamicMetaObjectProvider interface, providing default processing. You can see the code DynamicXml class, and the comparison of two methods in the UseDynamic class, NormalMethod(), and DynamicMethod(). NormalMethod() uses general xml data reading, and DynamicMethod() uses custom dynamic objects to parse xml content.
View Code![]()
[Serializable] [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class MyDescriptionAttribute : Attribute { } public class UseDynamic { public static void Test() { dynamic data = "Hello! My name is Inigo Montoya"; Console.WriteLine(data); data = (double)data.Length; data = data * 3.5 + 28.6; if (data == 2.4 + 112 + 26.2) { Console.WriteLine("data for length : {0}", data); } else { data.NonExistentMethodCallStillCompiles(); } } public static void NormalMethod() { XElement person = XElement.Parse("<Person><Name>Lord God</Name><Age>26</Age></Person>"); Console.WriteLine("{0},{1}", person.Descendants("Name").FirstOrDefault().Value, person.Descendants("Age").FirstOrDefault().Value); } public static void DynamicMethod() { dynamic person = DynamicXmL.Parse("<Person><Name>Lord God</Name><Age>26</Age></Person>"); Console.WriteLine("{0},{1}", person.Name, person.Age); } } /// <summary> /// Implementing custom dynamic objects /// </summary> public class DynamicXmL : DynamicObject { private XElement element; public DynamicXmL(XElement xElement) { element = xElement; } public static dynamic Parse(string text) { return new DynamicXmL(XElement.Parse(text)); } public override bool TryGetMember(GetMemberBinder binder, out object result) { bool success = false; result = null; XElement firstDescendant = element.Descendants(binder.Name).FirstOrDefault(); if (firstDescendant != null) { if (firstDescendant.Descendants().Count() > 0) { result = new DynamicXmL(firstDescendant); } else { result = firstDescendant.Value; } success = true; } return success; } public override bool TrySetMember(SetMemberBinder binder, object value) { bool success = false; XElement firstDescendant = element.Descendants(binder.Name).FirstOrDefault(); if (firstDescendant != null) { if (value.GetType() == typeof(XElement)) { firstDescendant.ReplaceWith(value); } else { firstDescendant.Value = value.ToString(); } success = true; } return success; } }