• 我心中的核心组件(可插拔的AOP)~第十二回 IoC组件Unity


    回到目录

    说在前

    Ioc组件有很多,之前也介绍过autofac,castle等,今天再来说一下在微软Nlayer DDD架构里使用的unity组件,今天主要说一下依靠注入,如果希望看拦截的用法,可以阅读这篇文章第十三回 实现AOP的拦截组件Unity.Interception

    做在后

    unity的用法主要说一下接口注入方法,它包括了程序中注入和配置文件注入,而接口注入还分为普通接口注入和泛型接口注入,下面分别来说一下:

    普通接口和类实现代码

      public interface IUser
        {
            IQueryable<WebManageUsers> GetEntities();
        }
       public class UserRepository : BackgroundRepository<WebManageUsers>, IUser
        {
            public IQueryable<WebManageUsers> GetEntities()
            {
                return this.GetModel();
            }
        }

    普通接口注入,程序中的注入

       using (IUnityContainer container = new UnityContainer())
                    {
                       container.RegisterType<IUser, DataTest.UserRepository>();
                        var repository = container.Resolve<IUser>();
                    }

    普通接口注入,配置文件中的注入

      <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
        <container>
          <register  type="EntityTest.IUser,EntityTest" mapTo="DataTest.UserRepository, DataTest" />
           </container>
      </unity>
     using (IUnityContainer container = new UnityContainer())
                    {
                        ConfigurationManager.GetSection("unity");
                        UnityConfigurationSection.CurrentSection.Configure(container);
                        var repository = container.Resolve<IUser>();
                    }

    普通接口和类实现代码

     /// <summary>
        /// 基础的数据操作规范
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        public interface IRepository<TEntity>
               where TEntity : class
        {
            /// <summary>
            /// 添加实体并提交到数据服务器
            /// </summary>
            /// <param name="item">Item to add to repository</param>
            void Insert(TEntity item);
    
            /// <summary>
            /// 移除实体并提交到数据服务器
            /// 如果表存在约束,需要先删除子表信息
            /// </summary>
            /// <param name="item">Item to delete</param>
            void Delete(TEntity item);
    
            /// <summary>
            /// 修改实体并提交到数据服务器
            /// </summary>
            /// <param name="item"></param>
            void Update(TEntity item);
    
            /// <summary>
            /// 得到指定的实体集合(延时结果集)
            /// Get all elements of type {T} in repository
            /// </summary>
            /// <returns>List of selected elements</returns>
            IQueryable<TEntity> GetModel();
    
            /// <summary>
            /// 根据主键得到实体
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            TEntity Find(params object[] id);
        }
        public class BackgroundRepository<T> : IRepository<T> where T : class
        {
    #region IRepository<TEntity> 成员
    
            public virtual void Insert(TEntity item)
            {
                OnBeforeSaved(new SavedEventArgs(item, SaveAction.Insert));
                Db.Entry<TEntity>(item);
                Db.Set<TEntity>().Add(item);
                this.SaveChanges();
                OnAfterSaved(new SavedEventArgs(item, SaveAction.Insert));
            }
    
            public virtual void Delete(TEntity item)
            {
                OnBeforeSaved(new SavedEventArgs(item, SaveAction.Delete));
                Db.Set<TEntity>().Attach(item);
                Db.Set<TEntity>().Remove(item);
                this.SaveChanges();
                OnAfterSaved(new SavedEventArgs(item, SaveAction.Delete));
            }
    
            public virtual void Update(TEntity item)
            {
                OnBeforeSaved(new SavedEventArgs(item, SaveAction.Update));
                Db.Set<TEntity>().Attach(item);
                Db.Entry(item).State = EntityState.Modified;
                this.SaveChanges();
                OnAfterSaved(new SavedEventArgs(item, SaveAction.Update));
            }
    
            /// <summary>
            /// 子类在实现时,可以重写,加一些状态过滤
            /// </summary>
            /// <returns></returns>
            public virtual IQueryable<TEntity> GetModel()
            {
                //  return Db.Set<TEntity>().AsNoTracking();//对象无法自动添加到上下文中,因为它是使用 NoTracking 合并选项检索的。请在定义此关系之前,将该实体显式附加到 ObjectContext。
                return Db.Set<TEntity>();////ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。
            }
            /// <summary>
            /// 得到原生态结果集
            /// </summary>
            /// <returns></returns>
            public IQueryable<TEntity> GetEntities()
            {
                return Db.Set<TEntity>();
            }
            #endregion
     }

    泛型接口注入,程序中的注入

      using (IUnityContainer container = new UnityContainer())
                    {
                       container.RegisterType<IRepository<User>, BackgroundRepository<User>>();
                        var re = container.Resolve<IRepository<User>>();
                    }

    泛型接口注入,配置文件中的注入

      <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
        <container>
             <register  type="IRepository.Core.IRepository`1,IRepository.Core" mapTo="DataTest.BackgroundRepository`1, DataTest" />
        </container>
      </unity>
      using (IUnityContainer container = new UnityContainer())
                    {
                        ConfigurationManager.GetSection("unity");
                        UnityConfigurationSection.CurrentSection.Configure(container);
                     var re = container.Resolve<IRepository<User>>();
                    }

    下面我们封装一个服务定位器,让它把Unity容器封装一下,方便以后调用它,下面是ServiceLocator的原代码:

      /// <summary>
        /// Represents the Service Locator.
        /// </summary>
        public sealed class ServiceLocator : IServiceProvider
        {
            #region Private Fields
            private readonly IUnityContainer _container;
            #endregion
    
            #region Private Static Fields
            private static readonly ServiceLocator instance = new ServiceLocator();
            #endregion
    
            #region Ctor
            /// <summary>
            /// Initializes a new instance of ServiceLocator class.
            /// </summary>
            private ServiceLocator()
            {
                UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
                _container = new UnityContainer();
                section.Configure(_container);
            }
            #endregion
    
            #region Public Static Properties
            /// <summary>
            /// Gets the singleton instance of the ServiceLocator class.
            /// </summary>
            public static ServiceLocator Instance
            {
                get { return instance; }
            }
            #endregion
    
            #region Private Methods
            private IEnumerable<ParameterOverride> GetParameterOverrides(object overridedArguments)
            {
                List<ParameterOverride> overrides = new List<ParameterOverride>();
                Type argumentsType = overridedArguments.GetType();
                argumentsType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                    .ToList()
                    .ForEach(property =>
                    {
                        var propertyValue = property.GetValue(overridedArguments, null);
                        var propertyName = property.Name;
                        overrides.Add(new ParameterOverride(propertyName, propertyValue));
                    });
                return overrides;
            }
            #endregion
    
            #region Public Methods
            /// <summary>
            /// Gets the service instance with the given type.
            /// </summary>
            /// <typeparam name="T">The type of the service.</typeparam>
            /// <returns>The service instance.</returns>
            public T GetService<T>()
            {
                return _container.Resolve<T>();
            }
            /// <summary>
            /// Gets the service instance with the given type by using the overrided arguments.
            /// </summary>
            /// <typeparam name="T">The type of the service.</typeparam>
            /// <param name="overridedArguments">The overrided arguments.</param>
            /// <returns>The service instance.</returns>
            public T GetService<T>(object overridedArguments)
            {
                var overrides = GetParameterOverrides(overridedArguments);
                return _container.Resolve<T>(overrides.ToArray());
            }
            /// <summary>
            /// Gets the service instance with the given type by using the overrided arguments.
            /// </summary>
            /// <param name="serviceType">The type of the service.</param>
            /// <param name="overridedArguments">The overrided arguments.</param>
            /// <returns>The service instance.</returns>
            public object GetService(Type serviceType, object overridedArguments)
            {
                var overrides = GetParameterOverrides(overridedArguments);
                return _container.Resolve(serviceType, overrides.ToArray());
            }
            #endregion
    
            #region IServiceProvider Members
            /// <summary>
            /// Gets the service instance with the given type.
            /// </summary>
            /// <param name="serviceType">The type of the service.</param>
            /// <returns>The service instance.</returns>
            public object GetService(Type serviceType)
            {
                return _container.Resolve(serviceType);
            }
    
            #endregion
        }

    下面再去使用unity时就方便多了,呵呵,看代码:

     var model = ServiceLocator.Instance.GetService<IExtensionRepository<WebManageUsers>>().GetModel().ToList();

    而使用ServiceLocator还有一个好处,就是不需要使用"实现的程序集",只要把"实现的程序集"和它的相关依赖的程序集一起复制到WEB项目的BIN目录即可,服务定位器会自己去定位的.

    好了,讲到这里也就差不多了,需要注意的是,如果你在项目中进行注入时,需要先注入的实现类所在的程序集也引入进来,否则也是不可以resolve出来对象的,而对于业务层(领域)层来说,不需要关心底层

    的实现技术,即不需要引用实现类的程序集,而在业务层引用接口程序集即可.

     回到目录

  • 相关阅读:
    ES6 Symbol数据类型和set-map 数据结构
    ES6的字符串和数值的扩展
    获取当前的网络状态
    节流阀
    stellar.js 视差滚动
    h5新增标签及css3新增属性
    vue中使用mui滑动条无法正常滑动
    用css3画有边框的三角形
    多个选项选中某一个的效果(用到siblings()方法)
    消除移动端按钮或者输入框等点击时出现边框
  • 原文地址:https://www.cnblogs.com/lori/p/3470685.html
Copyright © 2020-2023  润新知