QFramework 是一套 渐进式 的 快速开发 框架。目标是作为无框架经验的公司、独立开发者、以及 Unity3D 初学者们的 第一套框架。框架内部积累了多个项目的在各个技术方向的解决方案。学习成本低,接入成本低,重构成本低,二次开发成本低,文档内容丰富(提供使用方式以及原理、开发文档)。github:https://github.com/liangxiegame/QFramework

 

看本篇文章之前,首先请看反射泛型 : C#面试题(二)(包含答案) ------ GC/反射泛型

 public interface ISingleton
 {        
        void OnSingletonInit();
 }

1.无生命周期单例模式

    框架官方介绍 : http://liangxiegame.com/post/2/

public abstract class Singleton<T> : ISingleton where T : Singleton<T>
	{
		protected static T mInstance;

		static object mLock = new object();

		protected Singleton()
		{
		}

		public static T Instance
		{
			get
			{
				lock (mLock)
				{
					if (mInstance == null)
					{
						mInstance = SingletonCreator.CreateSingleton<T>();
					}
				}

				return mInstance;
			}
		}
        //释放
		public virtual void Dispose()
		{
			mInstance = null;
		}

		public virtual void OnSingletonInit()
		{
		}
	}
public abstract class SingletonProperty<T> : ISingleton where T : Singleton<T>
	{
		protected static T mInstance;

		static object mLock = new object();

		protected SingletonProperty()
		{
		}

		public static T Instance
		{
			get
			{
				lock (mLock)
				{
					if (mInstance == null)
					{
						mInstance = SingletonCreator.CreateSingleton<T>();
					}
				}

				return mInstance;
			}
		}
        //释放
		public virtual void Dispose()
		{
			mInstance = null;
		}

		public virtual void OnSingletonInit()
		{
		}
	}
 using System;
    using System.Reflection;

    public static class SingletonCreator
    {
        public static T CreateSingleton<T>() where T : class, ISingleton
        {
            // 获取私有构造函数
            var ctors = typeof(T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
            
            // 获取无参构造函数
            var ctor = Array.Find(ctors, c => c.GetParameters().Length == 0);

            if (ctor == null)
            {
                throw new Exception("Non-Public Constructor() not found! in " + typeof(T));
            }

            // 通过构造函数,常见实例
            var retInstance = ctor.Invoke(null) as T;
            retInstance.OnSingletonInit();

            return retInstance;
        }
    }

知识点补充:

GetProperties(BindingFlags)说明:

Instance|Public:获取公共的的实例属性(非静态的)
Instance|NonPublic:获取非公共的的实例属性(非静态的)。(private/protect/internal)
Static|Public:获取公共的静态属性
Static|NonPublic:获取非公共的静态属性。(private/protect/internal)
Instance|Static|Public:获取公共的的实例或静态属性
Instance|Static|NonPublic:非获取公共的的实例或静态属性

Predicate:表示定义一组条件并确定指定对象是否符合这些条件的方法。

                 参考链接 : https://blog.csdn.net/ilipan/article/details/45481435

GetParameters() : 取出每个构造函数的所有参数 

 

2.有生命周期单例模式

       using UnityEngine;

	public abstract class MonoSingletonProperty<T> : MonoBehaviour, ISingleton where T : MonoSingleton<T>
	{
		protected static T mInstance = null;

		public static T Instance
		{
			get
			{
				if (mInstance == null)
				{
					mInstance = MonoSingletonCreator.CreateMonoSingleton<T>();
				}

				return mInstance;
			}
		}
        //初始化调用
		public virtual void OnSingletonInit()
		{

		}

		public virtual void Dispose()
		{
			if (MonoSingletonCreator.IsUnitTestMode)
			{
				var curTrans = transform;
				do
				{
					var parent = curTrans.parent;
					DestroyImmediate(curTrans.gameObject);
					curTrans = parent;
				} while (curTrans != null);

				mInstance = null;
			}
			else
			{
				Destroy(gameObject);
			}
		}

		protected virtual void OnDestroy()
		{
			mInstance = null;
		}
	}
  using System;
    //继承自MonoSingletonPath,是自定义属性
    public class QMonoSingletonPath : MonoSingletonPath
    {
        public QMonoSingletonPath(string pathInHierarchy) : base(pathInHierarchy) //给父类的mPathInHierarchy复制
        {
        }
    }

    [AttributeUsage(AttributeTargets.Class)] //限制使用在Class前面
    public class MonoSingletonPath : Attribute
    {
	private string mPathInHierarchy;

        public MonoSingletonPath(string pathInHierarchy)
        {
            mPathInHierarchy = pathInHierarchy;
        }

        public string PathInHierarchy
        {
            get { return mPathInHierarchy; }
        }
    }
using System.Reflection;
	using UnityEngine;
	
	public static class MonoSingletonCreator
	{
		public static bool IsUnitTestMode { get; set; }

		public static T CreateMonoSingleton<T>() where T : MonoBehaviour, ISingleton
		{
			T instance = null;

			if (!IsUnitTestMode && !Application.isPlaying) return instance;
			instance = Object.FindObjectOfType<T>(); //搜索当前场景有没有实例

			if (instance != null) return instance;
			MemberInfo info = typeof(T);
                        //获取自定义的属性 
			var attributes = info.GetCustomAttributes(true);
			foreach (var atribute in attributes)
			{
                              //转化成MonoSingletonPath类
                               var defineAttri = atribute as MonoSingletonPath;
				if (defineAttri == null)
				{
					continue;
				}
                //defineAttri.PathInHierarchy获取路径,根据路径创建组件
                instance = CreateComponentOnGameObject<T>(defineAttri.PathInHierarchy, true);
				break;
			}
            //如果没有根据路径创建
			if (instance == null)
			{
				var obj = new GameObject(typeof(T).Name); //用类型的名字创建物体
				if (!IsUnitTestMode)
					Object.DontDestroyOnLoad(obj);
				instance = obj.AddComponent<T>(); //在该名字上添加组件
			}

			instance.OnSingletonInit();

			return instance;
		}
        //根据路径寻找/创建,添加脚本组件
		private static T CreateComponentOnGameObject<T>(string path, bool dontDestroy) where T : MonoBehaviour
		{
			var obj = FindGameObject(path, true, dontDestroy);
			if (obj == null)
			{
				obj = new GameObject("Singleton of " + typeof(T).Name);
				if (dontDestroy && !IsUnitTestMode)
				{
					Object.DontDestroyOnLoad(obj);
				}
			}

			return obj.AddComponent<T>();
		}
        //第二个参数是没有找到就创建此路径
		private static GameObject FindGameObject(string path, bool build, bool dontDestroy)
		{
			if (string.IsNullOrEmpty(path))
			{
				return null;
			}

			var subPath = path.Split('/');
			if (subPath == null || subPath.Length == 0)
			{
				return null;
			}

			return FindGameObject(null, subPath, 0, build, dontDestroy);
		}

		private static GameObject FindGameObject(GameObject root, string[] subPath, int index, bool build, bool dontDestroy)
		{
			GameObject client = null;

			if (root == null)
			{
				client = GameObject.Find(subPath[index]);
			}
			else
			{
				var child = root.transform.Find(subPath[index]);
				if (child != null)
				{
					client = child.gameObject;
				}
			}

			if (client == null) //没有找到此路径则创建路径
			{
				if (build)
				{
					client = new GameObject(subPath[index]);
					if (root != null)
					{
						client.transform.SetParent(root.transform);
					}

					if (dontDestroy && index == 0 && !IsUnitTestMode)
					{
						GameObject.DontDestroyOnLoad(client);
					}
				}
			}

			if (client == null)
			{
				return null;
			}

			return ++index == subPath.Length ? client : FindGameObject(client, subPath, index, build, dontDestroy);
		}
	}

使用举例:

[QMonoSingletonPath("[Main]/MainManager")]
	public class MainManager : ManagerBase,ISingleton
	{
		public static MainManager Instance
		{
			get { return MonoSingletonProperty<MainManager>.Instance; }
		}
		
		public void OnSingletonInit()
		{
			
		}

		public void Dispose()
		{
			MonoSingletonProperty<MainManager>.Dispose();
		}


		public void Enter()
		{
			
		}
	}
	public class MainManager : ManagerBase,ISingleton
	{
		public static MainManager Instance
		{
			get { return MonoSingletonProperty<MainManager>.Instance; }
		}
		
		public void OnSingletonInit()
		{
			
		}

		public void Dispose()
		{
			MonoSingletonProperty<MainManager>.Dispose();
		}


		public void Enter()
		{
			
		}
	}

 

补充知识点:

 

1.C# AttributeUsage的使用浅析

2.C#如何创建自定义控件以及添加自定义属性和事件使用

3.C#中自定义属性的例子

4.Unity3D游戏开发】GameObject.Find()、Transform.Find查找隐藏对象 (十)

 

因为笔者开始参与框架的维护,也希望各位能多多支持~

我们不只是提供框架,更教你学会搭建框架

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐