Do you really understand IOC and AOP? (2)

Source: Internet
Author: User
Iii. Factory Model Based on configuration file and reflection

To eliminate the dependency of mainapp on other components, we introduce the factory mode and use the reflection technology provided by. Net to assemble objects according to the Assembly procedure specified in the configuration file. This part of the Code only provides a function demonstration. If the actual application still needs to be improved (we recommend using some formed IOC frameworks, such as spring.net or Castle ). The dependency between components of the transformed system is as follows:

It can be seen that this time the real "programming for interfaces" is implemented ". All components only depend on interfaces. The objects required by mainapp are dynamically created and assembled by the factory based on the configuration file. When the system requirements change, you only need to modify the configuration file. In addition, there is no dependency between mainapp, sayhello, and hellogenerator, which achieves loose coupling.

How is this implemented? First, we must be able to parse the information in the configuration file and then create an object containing the relevant information. Finally, the object is created using the reflection mechanism based on the information. First, let's take a look at the content contained in the configuration file:

<?xml version="1.0" encoding="utf-8" ?><configuration>   <configSections>      <sectionGroup name="IocInCSharp">         <section name="objects" type="IocInCSharp.ConfigHandler, MainApp" />      </sectionGroup>   </configSections>   <IocInCSharp>      <objects>         <object name="SayHello" assembly="SayHello.dll" typeName="IocInCSharp.SayHello">            <property name="HelloGenerator" assembly="HelloGenerator.dll"                       typeName="IocInCSharp.CnHelloGenerator"></property>         </object>      </objects>   </IocInCSharp></configuration>

We can see that we have implemented an iocincsharp. confighandler class to process the content in the iocincsharp \ objects node in the configuration file. The confighandler class will process and create a configinfo object based on the content of the node (for the code about configinfo, objectinfo, and propertyinfo, you can view the source code by yourself. I will not go into details here ). The confighandler class code is implemented as follows:

using System;using System.Configuration;using System.Xml;namespace IocInCSharp{   public class ConfigHandler:IConfigurationSectionHandler   {      public object Create(object parent, object configContext, System.Xml.XmlNode section)      {         ObjectInfo info;         PropertyInfo propInfo;         ConfigInfo cfgInfo = new ConfigInfo();         foreach(XmlNode node in section.ChildNodes)         {            info = new ObjectInfo();            info.name = node.Attributes["name"].Value;            info.assemblyName = node.Attributes["assembly"].Value;            info.typeName = node.Attributes["typeName"].Value;            foreach(XmlNode prop in node)            {               propInfo = new PropertyInfo();               propInfo.propertyName = prop.Attributes["name"].Value;               propInfo.assemblyName = prop.Attributes["assembly"].Value;               propInfo.typeName = prop.Attributes["typeName"].Value;               info.properties.Add(propInfo);            }            cfgInfo.Objects.Add(info);         }         return cfgInfo;      }   }}

Through confighandler parsing, we finally get a configinfo instance. The factory generates and assembles the required Objects Based on the configuration information contained in the instance using reflection technology. The sayhellofactory code is as follows:

using System;using System.IO;using System.Configuration;using System.Reflection;namespace IocInCSharp{   public class SayHelloFactory   {      public static object Create(string name)      {         Assembly assembly;         object o = null;         object p;         string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) +                            Path.DirectorySeparatorChar;         ConfigInfo cfgInfo = (ConfigInfo)ConfigurationSettings.GetConfig("IocInCSharp/objects");          ObjectInfo info = cfgInfo.FindByName(name);         if(info != null)         {            assembly = Assembly.LoadFile(rootPath + info.assemblyName);            o = assembly.CreateInstance(info.typeName);            Type t = o.GetType();            for(int i=0; i<info.properties.Count; i++)            {                              PropertyInfo prop = (PropertyInfo)info.properties[i];                              assembly = Assembly.LoadFile(rootPath + prop.assemblyName);               p = assembly.CreateInstance(prop.typeName);               t.InvokeMember(prop.propertyName,                   BindingFlags.DeclaredOnly |                   BindingFlags.Public | BindingFlags.NonPublic |                   BindingFlags.Instance | BindingFlags.SetProperty, null, o, new Object[] {p});            }         }         return o;      }   }}

In the above Code, pay attention to the usage of the three commands:

assembly = Assembly.LoadFile(rootPath + prop.assemblyName);p = assembly.CreateInstance(prop.typeName);t.InvokeMember(prop.propertyName,    BindingFlags.DeclaredOnly |    BindingFlags.Public | BindingFlags.NonPublic |    BindingFlags.Instance | BindingFlags.SetProperty, null, o, new Object[] {p});

Assembly.LoadFile()Used to load external files;assembly.CreateInstance()Creates an object of the specified type based on the loaded assembly;t.InvokeMember(prop.propertyName, ........BindingFlags.SetProperty, null, o, new Object[] {p})Use the reflection mechanism to set attribute values for the created object.

In this way, our factory dynamically loads the Assembly according to the configuration file, dynamically creates objects, and sets attributes. With this factory, the content in mainapp is very simple:

using System;namespace IocInCSharp{   public class MainApp   {      public static void Main()      {         ISayHello sayHello = (ISayHello)SayHelloFactory.Create("SayHello");         if(sayHello != null)            sayHello.SayHelloTo("zhenyulu");         else            Console.WriteLine("Got an Error!");      }   }}

Currently, mainapp only depends on interfaces and does not depend on other components. It achieves loose coupling. In this example, you can tryIocInCSharp.CnHelloGeneratorChangeIocInCSharp.EnHelloGeneratorTo see if the output content is changed from Chinese to English. This is the effect of "injection.

From the above example, we can see that through the custom configuration file and the reflection technology in. net, we can develop the IOC application and assemble the corresponding objects according to the configuration file information. However, reflection programming has a high technical threshold, and in actual application, the configuration file format and handler design are not as simple as the above Code. Fortunately, we now have a lot of IOC containers to choose from. They all provide a complete dependency injection method and are more mature and stable than self-writing code. Using these frameworks allows programmers to complete "injection" in three or two lines of code. In our next case, we will use spring.net to implement dependency injection. We will find that only a few lines of code can be added and the configuration file can be changed to easily implement dependency injection. (To be continued)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.