C#利用反射机制动态创建泛型接口实例

Author Avatar
James Yeung 3月 21, 2016
  • 在其它设备中阅读本文章

我很懒,不希望写重复的copy代码,所以希望在写代码时能尽量简化和重用,一些设计上有但没必要的能不写就不写,但当然必须要实现。

最近学会用C#的反射机制,觉得非常好,可以通过类名实例化一个对应的对象。于是我就想到了在设计业务层时,一些通用的数据库操作是以泛型基类的形式供给各个模型使用的,只需替换传入的模型的类型参数,即刻操作相应的模型,而对于一些模型需要的特殊操作,则以这个基类派生出包含特殊方法的子类来实现。

但是这里会出现一些问题,就是在各层透明的情况下,其他层是不知道模型是否包含有特殊的方法,最初的解决方法是为每个模型都写一个继承业务基类的子类,就算它里面是空的(没有特殊方法)。而现在,通过反射,我们可以很好地实现统一的业务实例化操作,实现自动判断该模型是否拥有对应的业务子类。

先设计一个泛型接口IService<T>,声明两个方法:

namespace Service
{
   public Interface IService<T> where T : class
   {

      IRepository<T> _repo { get; }
      void SetRespository(IRepository<T> repo);
      T Add(T entity);
      bool Update(T entity);
   }
}

然后再写一个基础类,继承这个接口:

namespace Service
{
      public class BaseService<T> : IService<T> where T : class
    {
        IRepository<T> _repo ;
        public void SetRespository(IRepository<T> repo)
        {
            _repo=repo;
        }
        public T Add(T entity){}
        public bool Update(T entity){}
    }
}

设计业务工厂类,提供统一的实例化出口

    /// <summary>
    /// 业务工厂类
    /// <para>所有业务类都必须从这里产生</para>
    /// </summary>
    public class ServiceFactory
    {
        //获取当前程序集中的所有类的类型
        static Type[] ts = Assembly.GetExecutingAssembly().GetTypes();

        /// <summary>
        /// 动态映射创建实现了IService<T>接口的实例
        /// <para>如果字符集中已有继承了BaseService<T>的类,则返回该类的实例,
        /// 否则返回BaseService<T> 的实例</para>
        /// </summary>
        /// <typeparam name="T">数据模型</typeparam>
        /// <param name="repo">仓储实例</param>
        /// <returns>实现IService<T>接口的实例对象</returns>
        public static IService<T> GetService<T>(IRepository repo) where T : class
        {
            //获取传入类型的 System.Type 对象
            Type TType = typeof(T);
            //取当前线程内存块中可能已存储的Service对象
            var _service = CallContext.GetData($"BaseService<{TType.Name}>") as IService<T>;

            if (_service != null) return _service;
            //查询扩展业务类是否存在于程序集中
            Type _class = ts.FirstOrDefault(o => o.Name.Equals(TType.Name + "Service"));
            try
            {
                if (_class != null)
                {
                    _service = Activator.CreateInstance(_class) as IService<T>;
                }
                else
                {
                    _service = Activator.CreateInstance(typeof(BaseService<T>)) as IService<T>;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"无法实例化{typeof(BaseService<T>).Name}:{ex.Message}");
            }

            //获取泛型类定义的type类型
            var _repoType = repo.GetType().GetGenericTypeDefinition();
            //传入泛型类型参数
            _repoType = _repoType.MakeGenericType(typeof(T));
            //实例化仓储类
            var _repo = Activator.CreateInstance(_repoType) as IRepository<T>;
            //注入DbContext
            _repo.SetDbContext(repo.db);
            //注入仓储类
            _service.SetRespository(_repo);

            //将对象保存到当前线程的内存块中
            CallContext.SetData($"BaseService<{TType.Name}>", _service);
            return _service;
        }
    }

本文原创授权为:署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0) 协议普通文本 | 协议法律文本
本文链接:https://yangshunjie.com/dong-tai-chuang-jian-fan-xing-jie-kou-shi-li.html