这第一篇,同样讲的是spring的IOC功能,是如何实现通过注解来加载Bean文件的。
这是java版本的姐妹篇,C#版本。
文章原创,转载请注明出处www.neohope.org
经过无限精简之后,整体流程为:
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.org