引言
使用[Inject]标签,可以根据字段类型自动注入一些数据 是非常好使用 方便调用类与类之间的成员 和 函数 避免重复获取组件 游戏开始只读取一次 就可以直到游戏关闭为止
注入方式(成功 和 注销)
新建XX类 需要挂到Hierarchy面板上 任意一个物体
举个子列先挂到Canvas 需要注入A类
代码如下:
public class XX : MonoBehaviour
{
void Awake()
{
A a = GameObject.Find(“Canvas”).GetComponent< A >();
EasyInjector.Instance.AddInject(a);
}
void OnDestroy()
{
EasyInjector.Instance.RemoveInject<A>();
}
}
注意一点: 必须要说到 A类注入成功了 在Awake 里面函数 但是如果切换场景时, 那就必须要移除 A类注入方式 在OnDestroy()函数里面 , 如果再切回来场景时发现之前注入A类 没有被注销的话 就会导致重复注入A类成功 就会出现其他未知BUG
使用方式
由于上面已经讲了如何注入和注销,如何使用 首先必须要继承MonoInjected ,单独写一个MonoInjected
代码如下
// 可注入的Mono基类,所有子类如果复写Awake, 需要base.Awake();
public class MonoInjected : MonoBehaviour
{
protected virtual void Awake()
{
EasyInjector.ReflectionInject(this);
}
}
只允许继承它 才可以使用注入标签方式
比如你A类 需要调用B类一些成员那么 代码如下
public class A : MonoInjected
{
[Inject]
public B m_b { get; set; };
public void Start()
{
m_b.成员或者函数;//前提是 B类成员和函数 得public 公开 否则无法调用
}
}
注入工具代码
直接上代码
public class EasyInjector
{
protected Dictionary<Type, object> m_dicInjection; // 注入的类型和实例
protected Dictionary<Type, List<InjectVO>> m_dlInjected; // 已成功注入属性
protected Dictionary<Type, List<InjectVO>> m_dlUnjected; // 未成功注入属性
protected static EasyInjector _instance = null;
public static EasyInjector Instance
{
get
{
if (_instance == null)
{
_instance = new EasyInjector();
_instance.m_dicInjection = new Dictionary<Type, object>();
_instance.m_dlInjected = new Dictionary<Type,List<InjectVO>>();
_instance.m_dlUnjected = new Dictionary<Type,List<InjectVO>>();
}
return _instance;
}
}
//调用 注入成功函数
public void AddInject<T>(T obj)
{
Type tt = typeof(T);
if (m_dicInjection.ContainsKey(tt))
m_dicInjection[tt] = obj;
else
m_dicInjection.Add(tt, obj);
if (m_dlUnjected.ContainsKey(tt))
{
if (!m_dlInjected.ContainsKey(tt))
m_dlInjected.Add(tt, new List<InjectVO>());
foreach (InjectVO ij in m_dlUnjected[tt])
{
ij.injectPpt.SetValue(ij.injectObj, obj, null);
m_dlInjected[tt].Add(ij);
}
m_dlUnjected.Remove(tt);
}
}
public void AddInject(Type type, object obj)
{
if (m_dicInjection.ContainsKey(type))
m_dicInjection[type] = obj;
else
m_dicInjection.Add(type, obj);
if (m_dlUnjected.ContainsKey(type))
{
if (!m_dlInjected.ContainsKey(type))
m_dlInjected.Add(type, new List<InjectVO>());
foreach (InjectVO ij in m_dlUnjected[type])
{
ij.injectPpt.SetValue(ij.injectObj, obj, null);
m_dlInjected[type].Add(ij);
}
m_dlUnjected.Remove(type);
}
}
// 需要注销注入 调用移除函数
public void RemoveInject<T>()
{
Type tt = typeof(T);
if (m_dicInjection.ContainsKey(tt))
m_dicInjection.Remove(tt);
if (m_dlInjected.ContainsKey(tt))
{
if (!m_dlUnjected.ContainsKey(tt))
m_dlUnjected.Add(tt, new List<InjectVO>());
foreach (InjectVO ij in m_dlInjected[tt])
{
ij.injectPpt.SetValue(ij.injectObj, null, null);
m_dlUnjected[tt].Add(ij);
}
m_dlInjected.Remove(tt);
}
}
public T GetInject<T>()
{
Type tt = typeof(T);
if (m_dicInjection.ContainsKey(tt))
return (T)m_dicInjection[tt];
return default(T);
}
public object GetInject(Type t)
{
if (m_dicInjection.ContainsKey(t))
return m_dicInjection[t];
return null;
}
protected void Injection(object injectTarget)
{
Type tp = injectTarget.GetType();
MemberInfo[] members = tp.FindMembers(MemberTypes.Property,
BindingFlags.FlattenHierarchy |
BindingFlags.SetProperty |
BindingFlags.Public |
BindingFlags.Instance,
null, null);
foreach (MemberInfo member in members)
{
object[] injections = member.GetCustomAttributes(typeof(Inject), true);
if (injections.Length > 0)
{
//Inject attr = injections[0] as Inject;
PropertyInfo ppt = member as PropertyInfo;
Type pptType = ppt.PropertyType;
var obj = EasyInjector.Instance.GetInject(pptType);
if (obj == null) // 尚未注入的对象
{
if (!m_dlUnjected.ContainsKey(pptType))
m_dlUnjected.Add(pptType, new List<InjectVO>());
m_dlUnjected[pptType].Add(new InjectVO(injectTarget, ppt));
}
else // 已注入的对象
{
if (!m_dlInjected.ContainsKey(pptType))
m_dlInjected.Add(pptType, new List<InjectVO>());
m_dlInjected[pptType].Add(new InjectVO(injectTarget, ppt));
ppt.SetValue(injectTarget, obj, null);
}
}
}
}
public static void ReflectionInject(object c)
{
EasyInjector.Instance.Injection(c);
}
public class InjectVO
{
public object injectObj;
public PropertyInfo injectPpt;
public InjectVO(object target, PropertyInfo pptInfo)
{
injectObj = target;
injectPpt = pptInfo;
}
}
}
// 在非Mono中使用注入,需要在类构造函数中调用 EasyInjector.ReflectionInject(this);
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false,Inherited = true)]
public class Inject : Attribute
{
public Inject() { }
public Inject(object n)
{
name = n;
}
public object name { get; set; }
}