这第一篇,同样讲的是spring的IOC功能,是如何实现通过注解来加载Bean文件的。
这是java版本的姐妹篇,C#版本。
文章原创,转载请注明出处www.neohope.com
经过无限精简之后,整体流程为:
1、初始化bean工厂
bean工厂根据配置,加载带有指定attribute的类,并放到了Dictionary中
2、从bean工厂获取一个bean
通过bean的id,实例化一个类,并返回
需要的前置知识为:
1、spring的基本知识
2、反射
然后是源码:
1、TestAttribute.cs
这是个Attribute类,声明了一个新的注解类型,用于表示bean及bean的名字
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestAttribute { [AttributeUsage(AttributeTargets.Class)] class TestAttribute : System.Attribute { public String Ntype { get; set; } public String Nname { get; set; } public String Nauthor { get; set; } public String Nversion { get; set; } public String Nmsg { get; set; } } }
2、TestBean.cs
这是个Bean,使用了Attribute作为标识,是用于具体加载的类
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestAttribute { [TestAttribute(Nname = "testbean", Nauthor = "neohope", Ntype = "BEAN", Nmsg = "this is just a message", Nversion = "1.0")] class TestBean { public String name; public int age; public String sex; } }
3、ClassPathScanner.cs
通过指定assembly名,扫描assembly下所有的类型
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; namespace TestAttribute { /// <summary> /// The class path scanner /// </summary> class ClassPathScanner { /// <summary> /// Get all assemblies in current domain <see cref="System.Reflection.Assembly"/>. /// </summary> /// <returns>string set of assembly name</returns> public static String[] FindAllAssembliesInCurrentDomain() { List<String> result = new List<String>(); foreach (System.Reflection.Assembly assembly in System.AppDomain.CurrentDomain.GetAssemblies()) { result.Add(assembly.GetName().Name); } return result.ToArray(); } /// <summary> /// Get all module in current assembly /// </summary> /// <returns>string set of module name</returns> public static String[] FindAllModuleInThisAssembly() { List<String> result = new List<String>(); //Assembly thisAssembly = this.GetType().Assembly; Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly(); foreach (Module item in thisAssembly.GetModules()) { result.Add(item.Name); } return result.ToArray(); } /// <summary> /// Get all type in current assembly /// </summary> /// <returns>string set of type name</returns> public static String[] FindAllTypeInThisAssembly() { List<String> result = new List<String>(); //Assembly thisAssembly = this.GetType().Assembly; Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly(); foreach (Type item in thisAssembly.GetTypes()) { result.Add(item.Name); } return result.ToArray(); } /// <summary> /// Get all type in the assembly /// </summary> /// <param name="assemblyName">the name of the assembly</param> /// <returns>Type set in the assembly</returns> public static Type[] FindAllTypeInAssemblyByName(String assemblyName) { Assembly theAssembly = null; foreach (System.Reflection.Assembly assembly in System.AppDomain.CurrentDomain.GetAssemblies()) { if (assembly.GetName().Name.Equals(assemblyName)) { theAssembly = assembly; break; } } if (theAssembly == null) return new Type[] { }; List<Type> result = new List<Type>(); foreach (Type item in theAssembly.GetTypes()) { result.Add(item); } return result.ToArray(); } } }
4、ClassAttributeScanner.cs
工厂类,初始化时,通过attribute过滤bean,并将bean的名称及type放到dictionary中
获取实例时,通过bean名称,获取type,并实例化,返回
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; namespace TestAttribute { internal class ClassAttributeScanner { /// <summary> /// Dictionary of bean name and bean class /// </summary> private static Dictionary<String, Type> beanDict = new Dictionary<string, Type>(); /// <summary> /// Load all bean class with attribute from package /// </summary> /// <param name="assemblyName">the name of the assembly</param> /// <returns></returns> protected static void loadBeanTypes(String assemblyName) { Type[] allTypes = ClassPathScanner.FindAllTypeInAssemblyByName(assemblyName); foreach (Type aType in allTypes) { Attribute attribute = (TestAttribute)Attribute.GetCustomAttribute(aType, typeof(TestAttribute)); if (attribute == null) continue; TestAttribute ta = (TestAttribute)attribute; String beanName = ta.Nname; beanDict[beanName] = aType; } } /// <summary> /// init the bean factory /// </summary> /// <param name="assemblyName">the name of the assembly</param> /// <returns></returns> public static void InitBeanFactory(String assemblyName) { loadBeanTypes(assemblyName); } public static Object GetBean(String beanName) { Type theType = beanDict[beanName]; if (theType != null) { //return theType.Assembly.CreateInstance(theType.FullName); return Activator.CreateInstance(theType); } else { return null; } } } }
5、Program.cs
程序入口
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestAttribute { class Program { private static void Main(string[] args) { //String[] ret = ClassPathScanner.FindAllAssembliesInCurrentDomain(); //String[] ret = ClassPathScanner.FindAllModuleInThisAssembly(); //String[] ret = ClassPathScanner.FindAllTypeInThisAssembly(); //foreach (string s in ret) Console.WriteLine(s); ClassAttributeScanner.InitBeanFactory("TestAttribute"); TestBean bean = (TestBean)ClassAttributeScanner.GetBean("testbean"); bean.name = "neohope"; } } }
文章原创,转载请注明出处www.neohope.com