C ා design three-tier architecture based on interface Unity

Keywords: C# Unity Programming

Introduction

The purpose of interface oriented (Abstract) programming is to reduce the coupling degree of programs, and to conform to the principle of dependency inversion. Therefore, the typical three-tier architecture UI, BLL and DAL will be expanded to UI, IBLL, BLL, IDAL and DAL after they are designed based on the interface. In the last one< C. IOC learning notes >As we can see in, inversion of control (IoC) gives the creation of objects to third-party IoC containers such as Unity. With the IoC function of Unity, the three-tier architecture based on interface design can be further upgraded to build a more easily implemented configurable and extensible three-tier architecture; with the AOP function of Unity, the framework is more concise because it extracts the common logic components of the framework.

II. Project establishment

2.1 project establishment

Create a new project UI(Client), IBL, BLL, IDAL, DAL, Model, and Common.

2.2 project description

III. reference relationship between projects

3.1. Right click the project name - > Add - > reference - > project, and add the references of each project.

3.2 references

IV. NuGet package to be installed

 

V. precautions

Encapsulate the IoC call of the Unity Container. The Container should be encapsulated in the singleton mode to improve efficiency. MemoryCache is used here.

5.1. In the Common project, reference System.Runtime.Caching.dll, and create a new cache help class under the Helper folder: MemoryCacheHelper.cs.

    /// <summary>
    /// The memory cache help class supports three caching methods: absolute expiration time, sliding expiration time, and file dependency.
    /// </summary>
    class MemoryCacheHelper
    {
        private static readonly object _locker1 = new object(), _locker2 = new object();

        /// <summary>
        /// Retrieve the cache item, and return null if it does not exist.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T GetCacheItem<T>(string key)
        {
            try
            {
                return (T)MemoryCache.Default[key];
            }
            catch
            {
                return default(T);
            }
        }

        /// <summary>
        /// Whether to include the cache entry of the specified key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool Contains(string key)
        {
            return MemoryCache.Default.Contains(key);
        }

        /// <summary>
        /// Take the deferred item. If it does not exist, add a new one.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="cachePopulate"></param>
        /// <param name="slidingExpiration"></param>
        /// <param name="absoluteExpiration"></param>
        /// <returns></returns>
        public static T GetOrAddCacheItem<T>(string key, Func<T> cachePopulate, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key");
            if (cachePopulate == null) throw new ArgumentNullException("cachePopulate");
            if (slidingExpiration == null && absoluteExpiration == null) throw new ArgumentException("Either a sliding expiration or absolute must be provided");

            if (MemoryCache.Default[key] == null)
            {
                lock (_locker1)
                {
                    if (MemoryCache.Default[key] == null)
                    {
                        T cacheValue = cachePopulate();
                        if (!typeof(T).IsValueType && cacheValue == null)   //If reference type and NULL No cache
                        {
                            return cacheValue;
                        }

                        var item = new CacheItem(key, cacheValue);
                        var policy = CreatePolicy(slidingExpiration, absoluteExpiration);

                        MemoryCache.Default.Add(item, policy);
                    }
                }
            }

            return (T)MemoryCache.Default[key];
        }

        /// <summary>
        /// Take the deferred item. If it does not exist, add a new one.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="cachePopulate"></param>
        /// <param name="dependencyFilePath"></param>
        /// <returns></returns>
        public static T GetOrAddCacheItem<T>(string key, Func<T> cachePopulate, string dependencyFilePath)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key");
            if (cachePopulate == null) throw new ArgumentNullException("cachePopulate");

            if (MemoryCache.Default[key] == null)
            {
                lock (_locker2)
                {
                    if (MemoryCache.Default[key] == null)
                    {
                        T cacheValue = cachePopulate();
                        if (!typeof(T).IsValueType && cacheValue == null)   //If reference type and NULL No cache
                        {
                            return cacheValue;
                        }

                        var item = new CacheItem(key, cacheValue);
                        var policy = CreatePolicy(dependencyFilePath);

                        MemoryCache.Default.Add(item, policy);
                    }
                }
            }

            return (T)MemoryCache.Default[key];
        }

        /// <summary>
        /// Specifies a set of eviction and expiration details for cached items
        /// </summary>
        /// <param name="slidingExpiration"></param>
        /// <param name="absoluteExpiration"></param>
        /// <returns></returns>
        private static CacheItemPolicy CreatePolicy(TimeSpan? slidingExpiration, DateTime? absoluteExpiration)
        {
            var policy = new CacheItemPolicy();

            if (absoluteExpiration.HasValue)
            {
                policy.AbsoluteExpiration = absoluteExpiration.Value;
            }
            else if (slidingExpiration.HasValue)
            {
                policy.SlidingExpiration = slidingExpiration.Value;
            }

            policy.Priority = CacheItemPriority.Default;

            return policy;
        }

        /// <summary>
        /// Specifies a set of eviction and expiration details for cached items
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private static CacheItemPolicy CreatePolicy(string filePath)
        {
            CacheItemPolicy policy = new CacheItemPolicy();
            policy.ChangeMonitors.Add(new HostFileChangeMonitor(new List<string>() { filePath }));
            policy.Priority = CacheItemPriority.Default;
            return policy;
        }

        /// <summary>
        /// Remove cache entry for specified key
        /// </summary>
        /// <param name="key"></param>
        public static void RemoveCacheItem(string key)
        {
            if (Contains(key))
            {
                MemoryCache.Default.Remove(key);
            }
        }
    }

5.2. Create a new Unity help class: UnityHelper.cs under the Common project Helper folder, and implement the Container cache.

    /// <summary>
    /// Unity Container help class
    /// </summary>
    public static class UnityHelper
    {
        /// <summary>
        /// Unity Container creating objects(No alias)
        /// </summary>
        /// <param name="containerName">Container name</param>
        /// <returns></returns>
        public static T GetObject<T>(string containerName)
        {
            IUnityContainer container = MemoryCacheHelper.GetOrAddCacheItem(containerName, () =>
            {
                IUnityContainer unityContainer = new UnityContainer();
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap
                {
                    ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + @"ConfigFiles\Unity.config")
                };
                Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
                configSection.Configure(unityContainer, containerName);
                return unityContainer;
            },TimeSpan.FromMinutes(30),null);
            
            return container.Resolve<T>();
        }

        /// <summary>
        /// Unity Container creating objects(Alias)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="containerName">Container name</param>
        /// <param name="alisName">Object aliases</param>
        /// <returns></returns>
        public static T GetObject<T>(string containerName, string alisName)
        {
            IUnityContainer container = MemoryCacheHelper.GetOrAddCacheItem(containerName, () =>
            {
                IUnityContainer unityContainer = new UnityContainer();
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap
                {
                    ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + @"ConfigFiles\Unity.config")
                };
                Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
                configSection.Configure(unityContainer, containerName);
                return unityContainer;
            }, TimeSpan.FromMinutes(30), null);

            return container.Resolve<T>(alisName);
        }
    }

 

    Source download

Posted by ragtek on Sat, 21 Mar 2020 02:46:55 -0700