Use Asp.net cache (II)

Prequel -Asp.net use caching (a) to you a brief introduction

  1. What is Cache
  2. Why use caching
  3. Simple HttpRuntime.Cacheto use caching mechanisms

This program is to share the cache becomes more elastic


The second outline

  1. Proposed interface, improve exchangeability
  2. Use generic rewrite the cache read mode
  3. Use expansion method to rewrite the cache

  1. Proposed interface, improve exchangeability

Situation:

There are currently projects using  HttpRuntime.Cache objects

In addition to using the cache memory in Asp.Net HttpRuntime.Cacheoutside class, there are many solutions such as using Memcache , Redis ...

If we use the original HttpRuntime.Cacheclass but then they have to turn to other cache ways how to do?

public class HomeController : Controller
{
	System.Web.Caching.Cache cacheContainer = HttpRuntime.Cache;

	public ActionResult Index()
	{

		string cacheData = cacheContainer.Get("data") as string;

		if (cacheData==null)
		{
			cacheContainer.Insert("test1", DateTime.Now.ToShortDateString());
		}
  
		return View(cacheData);
	}
}

Although the use of different cache ways, but I remember my last article focused on the cache will have two actions, reading and writing , so there will be a basic reading and writing these two actions

OOP has a very important concept in  multiple classes have to consider making repetitive movements parent

In order to facilitate understanding I put HttpRuntime.Cachethe package into a class

public class NetCache {
    System.Web.Caching.Cache cacheContainer = HttpRuntime.Cache;
    public object GetCacheObject(string key) {
        return cacheContainer.Get(key);
    }

    public void SetCache(string key,object obj) {
        cacheContainer.Insert(key, obj);
    }
}

Here there is another Memcachecache Class

public class MemeryCache {
	private ObjectCache _cache = MemoryCache.Default;
	public object GetCacheObject(string key)
	{
		return _cache[cacheKey];
	}

	public void SetCache(string key, object obj)
	{
		var policy = new CacheItemPolicy();
		policy.RemovedCallback = OnFileContentsCacheRemove;
		// 设定缓存时间2分钟
		policy.AbsoluteExpiration = DateTimeOffset.Now.Minute(2);
		_cache.Set(cacheKey, fileContents, policy);
	}
}

To not focus on these two objects inside detail, we can see that they all have  GetCacheObject methods and SetCachemethods

Then we can propose in due course interface (interface) , as these two classes of contract

public interface ICache {

	void Set(string key,object obj);

	object Get(string key);
}

After their two class implements  ICache the interface

public class MemeryCache : ICache
{
	private ObjectCache _cache = MemoryCache.Default;
	public object Get(string key)
	{
		return _cache[cacheKey];
	}

	public void Set(string key, object obj)
	{
		var policy = new CacheItemPolicy();
		policy.RemovedCallback = OnFileContentsCacheRemove;
		// 设定缓存时间2分钟
		policy.AbsoluteExpiration = DateTimeOffset.Now.Minute(2);
		_cache.Set(cacheKey, fileContents, policy);
	}
}

public class NetCache : ICache
{
    System.Web.Caching.Cache cacheContainer = HttpRuntime.Cache;
    public object Get(string key) {
        return cacheContainer.Get(key);
    }
    
    public void Set(string key,object obj) {
        cacheContainer.Insert(key, obj);
    }
}

What are the benefits proposed interface?

We can change the program in front of IOC dependency injection way, do not use hard-coded in the program HttpRuntime.Cacheby the IOC container to help us to target injection program.

Note: I use constructor injection method

public class HomeController : Controller
{
    //不用写死使用  HttpRuntime.Cache
	//System.Web.Caching.Cache cacheContainer = HttpRuntime.Cache;
    ICache cacheContainer;
    public HomeController(ICache Container){
        cacheContainer = Container;
    }
    
	public ActionResult Index()
	{

		string cacheData = cacheContainer.Get("data") as string;

		if (cacheData==null)
		{
			cacheContainer.Insert("test1", DateTime.Now.ToShortDateString());
		}
  
		return View(cacheData);
	}
}

ICache Become caching program lubricant can make the program more flexible


  1. Use generic rewrite the cache read mode

My answer is the second way in StackOverFlow

The most important technique is the Getmethod returns Objectinto the use of generics

 public T GetOrSetCache
  
  
   
   
    (string key,T obj, int cacheTime) where T:class,new()
{
    System.Web.Caching.Cache cacheContainer = HttpRuntime.Cache;
    T cacheObj = cacheContainer.Get(key) as T;

    if (cacheObj == null)
    {
        cacheContainer.Insert(key,
            obj,
            null, 
            DateTime.Now.AddMinutes(cacheTime),
            System.Web.Caching.Cache.NoSlidingExpiration);
        cacheObj = obj;
    }

    return cacheObj;
}

  
  

Let us use can become

var data = DateTime.Now.ToShortDateString();
int numberOfMinutes = 3;
data = GetOrSetCache("name1",data,numberOfMinutes );

We just need to call the GetOrSetCachemethod, which the GetCacheand SetCachepackages up


  1. Use expansion method to rewrite the cache

.Net has provided a very convenient mechanism  expansion method , this mechanism to help us solve a very important question.
We can expand the package but did not have the source code of the class ,

During this procedure, use  may use  the expression, to make the program more concise !!Func lambda

public static TObj GetOrSetCache
  
  
   
   (this Func
   
   
    
     selector, string key, int cacheTime)    where TObj : class
{ 
	Cache cacheContainer = HttpRuntime.Cache;
	//get cache Object
	var obj = cacheContainer.Get(key) as TObj;

	//if there isn't cache object add this object to cache
	if (obj == null)
	{
		obj = selector();
		cacheContainer.Insert(key, obj);
	}

	return obj;
}

   
   
  
  

When we use the following

Change concise action more beautiful

int numberOfMinutes = 3;
data = GetOrSetCache(()=> DateTime.Now.ToShortDateString(),"name1",data,numberOfMinutes );

Plus with the field mapping:

With the use of extension methods and interfaces


public class WebDefaultCache : ICache
{
	Cache cacheContainer = HttpRuntime.Cache;
	public object Get(string key)
	{
		return cacheContainer.Get(key);
	}

	public void Set(string key, object obj)
	{
		cacheContainer.Insert(key, obj);
	}
}
public interface ICache{
	void Set(string key, object obj);

	object Get(string key);
}

public static class InfrastructureExtension
{
	public static TObj GetOrSetCache
  
  
   
   (this Func
   
   
    
     selector, string key) where TObj : class {
		return GetOrSetCache(selector, key,10);
	}

	public static TObj GetOrSetCache
    
    
     
     (this Func
     
     
      
       selector, string key, int cacheTime) where TObj : class
	{
		return GetOrSetCache(selector, key, cacheTime, new WebDefaultCache());
	}

	public static TObj GetOrSetCache
      
      
        (this Func 
       
         selector, string key, int cacheTime, ICache cacheContainer) where TObj : class { //get cache Object var obj = cacheContainer.Get(key) as TObj; //if there isn't cache object add this object to cache if (obj == null) { obj = selector(); cacheContainer.Set(key, obj); } return obj; } } 
        
      
     
     
    
    
   
   
  
  

Although the use of a third and as
yet we have much use method overloading more than pass a parameter ICacheinterface allows us to decide which way you want to use cache, do not go there to change the program when writing programs.

Plus with the field mapping program I put my own common ExtenionTool project


If you found this article helpful, you can pay the corner stone ^^ encourage infighting

Original: Big Box  Asp.net use caching (b)


Guess you like

Origin www.cnblogs.com/chinatrump/p/11490798.html