為了減少GetComponent的使用 依照ButterKnife的Unity ButterKnife
using System;
using System.Reflection;
using UnityEngine;
using System.Collections.Generic;
public class Knife : Singleton<Knife>
{
public void Bind (Component compon)
{
FieldInfo[] fields = compon.GetType ().GetFields ();
setInfoValue (fields, compon.gameObject, compon);
}
public T Bind<T> (GameObject go) where T : new()
{
T classType = new T ();
FieldInfo[] fields = typeof(T).GetFields ();
setInfoValue (fields, go, classType);
return classType;
}
void setInfoValue (FieldInfo[] fields, GameObject go, System.Object classType)
{
for (int j = 0; j < fields.Length; j++) {
FieldInfo info = fields [j];
var view = Attribute.GetCustomAttribute (info, typeof(DIAttribute));
if (view == null) {
continue;
}
Type type = info.FieldType;
if (view is BindView) {
BindView bindView = view as BindView;
if (type.IsArray) {
if (bindView.typeObj == null) {
Debug.LogErrorFormat ("{0}is get array , but typeof() is null, please check ", bindView.goPath);
return;
}
var parent = go.transform.Find (bindView.goPath);
Array filledArray = Array.CreateInstance (bindView.typeObj, parent.childCount);
for (int i = 0; i < parent.childCount; i++) {
var child = parent.transform.GetChild (i);
if (bindView.typeObj == typeof(GameObject)) {
filledArray.SetValue (child.gameObject, i);
} else {
filledArray.SetValue (child.gameObject.transform.GetOrAddComponent (bindView.typeObj), i);
}
}
info.SetValue (classType, filledArray);
} else {
var findChildGo = go.transform.FindChild (bindView.goPath);
if (findChildGo != null) {
if (type.Equals (typeof(GameObject))) {
info.SetValue (classType, findChildGo.gameObject);
} else {
info.SetValue (classType, findChildGo.gameObject.transform.GetOrAddComponent (type));
}
} else
Debug.LogErrorFormat ("[Parent]{0}.transform.FindChild(Path:{1}) is null,check GameObejct it exist and path is right.", go.name, bindView.goPath);
}
}
}
}
}
using UnityEngine;
using System;
public class BindView : DIAttribute
{
public readonly string goPath;
public readonly Type typeObj;
public BindView (string goPath, Type typeObj = null)
{
this.goPath = goPath;
this.typeObj = typeObj;
}
}
BindView繼承DIAttribute 代入指定GameOjbect的路徑
Knife在Bind的時候會知道要從哪個Comonent或GameObject身上取得FieldInfo[]的資訊
利用Attribute.GetCustomAttribute獲取要從哪個GameObject身上獲得哪個Component
如果指定的GameObject身上沒有該Component 就會新增並取得(GetOrAddComponent)
使用範例
單個Component取得
[BindView("scaler/Scroll View/Viewport/Content/round_set/set_toggle")]
public Toggle RoundSetToggle;
從scaler/Scroll View/Viewport/Content/round_set/set_toggle的GameObject上需要取得Toggle的Component
需設為Publich才找得到
取得的Component為Array
[BindView("scaler/sound", typeof(AudioSource))]
public AudioSource[] sound;
在scaler/sound下的所有child GetorAddComponent<AudioSource>();
Bind<T>使用
Holder holder = Knife.Instance.Bind<Holder> (gameObject);
在gameobject底下尋找Holder類別BindView