Files
2026-07-10 15:25:05 +08:00

424 lines
15 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Zhaizj.Framework.Reflection;
using Zhaizj.Framework.Web.Mvc;
using Zhaizj.Framework.Web.Mvc.Interface;
namespace Zhaizj.Framework.DI {
/// <summary>
/// IOC 管理容器
/// </summary>
public class ObjectContext {
private static readonly ILog logger = LogManager.GetLogger( typeof( ObjectContext ) );
private static Object syncRoot = new object();
private static volatile ObjectContext _instance;
private ObjectContext() {
}
/// <summary>
/// 容器的实例(单例)
/// </summary>
public static ObjectContext Instance {
get {
if (_instance == null) {
lock (syncRoot) {
if (_instance == null) {
ObjectContext ctx = new ObjectContext();
InitInject( ctx );
_instance = ctx;
}
}
}
return _instance;
}
}
private static void InitInject( ObjectContext ctx ) {
loadAssemblyAndTypes( ctx );
resolveAndInject( ctx );
addNamedObjects( ctx );
}
private Dictionary<String, Assembly> _assemblyList = new Dictionary<String, Assembly>();
private Dictionary<String, Type[]> _assemblyTypes = new Dictionary<String, Type[]>();
private Dictionary<String, Type> _typeList = new Dictionary<String, Type>();
private Dictionary<String, MapItem> _resolvedMap = new Dictionary<String, MapItem>();
private Hashtable _objectsContainerByName = new Hashtable();
private Hashtable _objectsContainerByType = new Hashtable();
private Dictionary<String, IDto> _dtoList = new Dictionary<string, IDto>();
/// <summary>
/// 所有纳入容器管理的程序集
/// </summary>
public Dictionary<String, Assembly> AssemblyList {
get { return _assemblyList; }
set { _assemblyList = value; }
}
/// <summary>
/// 所有程序集的 Dictionary
/// </summary>
public Dictionary<String, Type[]> AssemblyTypes {
get { return _assemblyTypes; }
set { _assemblyTypes = value; }
}
/// <summary>
/// 已经解析过的类型
/// </summary>
public Dictionary<String, MapItem> ResolvedMap {
get { return _resolvedMap; }
set { _resolvedMap = value; }
}
/// <summary>
/// 所有纳入容器管理的类型
/// </summary>
public Dictionary<String, Type> TypeList {
get { return _typeList; }
set { _typeList = value; }
}
/// <summary>
/// 根据名称罗列的对象表
/// </summary>
public Hashtable ObjectsByName {
get { return _objectsContainerByName; }
set { _objectsContainerByName = value; }
}
/// <summary>
/// 根据类型罗列的对象表
/// </summary>
public Hashtable ObjectsByType {
get { return _objectsContainerByType; }
set { _objectsContainerByType = value; }
}
/// <summary>
/// 获取所有的dto(工厂),用于创建dto对象
/// </summary>
public Dictionary<String, IDto> DtoList {
get { return _dtoList; }
set { _dtoList = value; }
}
//----------------------------------------------------------------------------------------------------
/// <summary>
/// 根据依赖注入的配置文件中的 name 获取对象
/// </summary>
/// <param name="objectName"></param>
/// <returns></returns>
public static Object GetByName( String objectName ) {
if (Instance.ResolvedMap.ContainsKey( objectName ) == false) return null;
MapItem item = Instance.ResolvedMap[objectName];
if (item == null) return null;
if (item.Singleton)
return Instance.ObjectsByName[objectName];
else
return createInstanceAndInject( item );
}
/// <summary>
/// 从缓存中取对象(有注入的就注入,没有注入的直接生成),结果是单例
/// </summary>
/// <param name="typeFullName"></param>
/// <returns></returns>
public static Object GetByType( String typeFullName ) {
if (Instance.TypeList.ContainsKey( typeFullName ) == false) return null;
Type t = Instance.TypeList[typeFullName];
return GetByType( t );
}
/// <summary>
/// 从缓存中取对象(有注入的就注入,没有注入的直接生成),结果是单例
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static Object GetByType( Type t ) {
if (t == null) return null;
Object result = Instance.ObjectsByType[t.FullName];
if (result == null) {
MapItem mapItem = getMapItemByType( t );
if (mapItem != null) {
result = createInstanceAndInject( mapItem );
}
else {
result = rft.GetInstance( t );
}
Instance.ObjectsByType[t.FullName] = result;
}
return result;
}
/// <summary>
/// 根据type,不从缓存(pool)中取,而是全新创建实例(有注入的就注入,没有注入的直接生成),肯定不是单例
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static Object CreateObject( Type t ) {
if (t == null) return null;
MapItem mapItem = getMapItemByType( t );
if (mapItem == null)
return rft.GetInstance( t );
else
return createInstanceAndInject( mapItem );
}
/// <summary>
/// 根据type,不从缓存(pool)中取,而是全新创建实例(有注入的就注入,没有注入的直接生成),肯定不是单例
/// </summary>
/// <param name="typeFullName"></param>
/// <returns></returns>
public static Object CreateObject( String typeFullName ) {
if (Instance.TypeList.ContainsKey( typeFullName ) == false) return null;
Type t = Instance.TypeList[typeFullName];
return CreateObject( t );
}
/// <summary>
/// 根据type,不从缓存(pool)中取,而是全新创建实例(有注入的就注入,没有注入的直接生成),肯定不是单例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T Create<T>() {
return (T)CreateObject( typeof( T ) );
}
private static MapItem getMapItemByType( Type t ) {
Dictionary<String, MapItem> resolvedMap = Instance.ResolvedMap;
foreach (KeyValuePair<String, MapItem> entry in resolvedMap) {
MapItem item = entry.Value;
if (t.FullName.Equals( item.Type )) return item;
}
return null;
}
private static Object createInstanceAndInject( MapItem item ) {
Object currentObject = rft.GetInstance( item.TargetObject.GetType() );
Dictionary<String, object> maps = item.Map;
if (maps.Count > 0) {
foreach (KeyValuePair<String, object> entry in maps) {
Object propertyValue = GetByName( entry.Value.ToString() );
if (propertyValue != null) {
ReflectionUtil.SetPropertyValue( currentObject, entry.Key, propertyValue );
}
}
}
return currentObject;
}
//----------------------------------------------------------------------------------------------
private static void loadAssemblyAndTypes( ObjectContext ctx ) {
String appSettings = cfgHelper.GetAppSettings( "InjectAssembly" );
if (strUtil.IsNullOrEmpty( appSettings )) return;
String[] strArray = appSettings.Split( new char[] { ',' } );
foreach (String asmStr in strArray) {
if (strUtil.IsNullOrEmpty( asmStr )) continue;
String asmName = asmStr.Trim();
Assembly assembly = loadAssemblyPrivate( asmName, ctx );
findTypesPrivate( assembly, asmName, ctx );
}
}
private static Assembly loadAssemblyPrivate( String asmName, ObjectContext ctx ) {
Assembly assembly = Assembly.Load( asmName );
ctx.AssemblyList.Add( asmName, assembly );
return assembly;
}
private static void findTypesPrivate( Assembly assembly, String asmName, ObjectContext ctx ) {
Type[] types = assembly.GetTypes();
ctx.AssemblyTypes.Add( asmName, types );
foreach (Type type in types) {
ctx.TypeList.Add( type.FullName, type );
if (rft.IsInterface( type, typeof( IDto ) )) {
ctx.DtoList.Add( strUtil.TrimEnd( type.FullName, "Dto" ), (IDto)rft.GetInstance( type ) );
}
}
}
/// <summary>
/// 加载程序集并返回此程序集,如果容器中已存在,则直接从容器中获取
/// </summary>
/// <param name="asmName"></param>
/// <returns></returns>
public static Assembly LoadAssembly( String asmName ) {
Assembly assembly;// = Instance.AssemblyList[asmName];
Instance.AssemblyList.TryGetValue( asmName, out assembly );
if (assembly == null) {
assembly = Assembly.Load( asmName );
Instance.AssemblyList.Add( asmName, assembly );
}
return assembly;
}
/// <summary>
/// 加载某程序集里的所有类型,如果容器中已存在,则直接从容器中获取
/// </summary>
/// <param name="asmName"></param>
/// <returns></returns>
public static Type[] FindTypes( String asmName ) {
Type[] types;// = Instance.AssemblyTypes[asmName];
Instance.AssemblyTypes.TryGetValue( asmName, out types );
if (types == null) {
types = LoadAssembly( asmName ).GetTypes();
Instance.AssemblyTypes.Add( asmName, types );
foreach (Type type in types) {
Instance.TypeList.Add( type.FullName, type );
}
}
return types;
}
//----------------------------------------------------------------------------------------------
private static void resolveAndInject( ObjectContext ctx ) {
List<MapItem> maps = cdb.findAll<MapItem>();
if (maps.Count <= 0) return;
Dictionary<String, MapItem> resolvedMap = new Dictionary<String, MapItem>();
logger.Info( "resolve item begin..." );
resolveMapItem( maps, resolvedMap, ctx );
logger.Info( "inject Object begin..." );
injectObjects( maps, resolvedMap );
ctx.ResolvedMap = resolvedMap;
}
private static void resolveMapItem( List<MapItem> maps, Dictionary<String, MapItem> resolvedMap, ObjectContext ctx ) {
foreach (MapItem oneMap in maps) {
Type type;// = ctx.TypeList[oneMap.Type];
ctx.TypeList.TryGetValue( oneMap.Type, out type );
if (type == null) continue;
logger.Info( "resolve:" + oneMap.Name );
if (oneMap.Singleton) {
// ObjectsByType中存储的都是单例对象
oneMap.TargetObject = checkByCache( type, ctx );
}
else {
oneMap.TargetObject = rft.GetInstance( type );
}
resolvedMap[oneMap.Name] = oneMap;
}
}
private static Object checkByCache( Type t, ObjectContext ctx ) {
if (ctx.ObjectsByType[t.FullName] == null) {
ctx.ObjectsByType.Add( t.FullName, rft.GetInstance( t ) );
}
return ctx.ObjectsByType[t.FullName];
}
private static void injectObjects( List<MapItem> mapItems, Dictionary<String, MapItem> resolvedMap ) {
foreach (MapItem item in mapItems) {
logger.Info( "inject:" + item.Name );
Dictionary<String, object> maps = item.Map;
if (maps.Count <= 0) continue;
foreach (KeyValuePair<String, object> entry in maps) {
logger.Info( "------inject key:" + entry.Key.ToString() );
MapItem referencedItem;// = resolvedMap[entry.Value.ToString()];
resolvedMap.TryGetValue( entry.Value.ToString(), out referencedItem );
if (referencedItem != null) {
ReflectionUtil.SetPropertyValue( item.TargetObject, entry.Key, referencedItem.TargetObject );
}
}
}
}
//--------------------------------------------------------------------------------
private static void addNamedObjects( ObjectContext ctx ) {
Dictionary<String, MapItem> resolvedMap = ctx.ResolvedMap;
Hashtable namedObjects = new Hashtable();
foreach (KeyValuePair<String, MapItem> entry in resolvedMap) {
MapItem item = entry.Value;
namedObjects.Add( item.Name, item.TargetObject );
}
ctx.ObjectsByName = namedObjects;
}
/// <summary>
/// 根据容器配置,将依赖关系注入到已创建的对象中
/// </summary>
/// <param name="obj"></param>
public static void Inject( Object obj ) {
if (obj == null) return;
Type t = obj.GetType();
Dictionary<String, MapItem> resolvedMap = ObjectContext.Instance.ResolvedMap;
foreach (KeyValuePair<String, MapItem> pair in resolvedMap) {
MapItem item = pair.Value;
if (item.Type.Equals( t.FullName ) == false) continue;
Dictionary<String, object> maps = item.Map;
if (maps.Count <= 0) return;
injectObjectSingle( obj, resolvedMap, maps );
return;
}
}
private static void injectObjectSingle( Object obj, Dictionary<String, MapItem> resolvedMap, Dictionary<String, object> maps ) {
foreach (KeyValuePair<String, object> entry in maps) {
logger.Info( "------inject key:" + entry.Key.ToString() );
MapItem referencedItem;
resolvedMap.TryGetValue( entry.Value.ToString(), out referencedItem );
if (referencedItem != null) {
ReflectionUtil.SetPropertyValue( obj, entry.Key, referencedItem.TargetObject );
}
}
}
}
}