List with timeout/expire ability
I need a function like this:
AddToList(txtName, timeExpire);
It looks like sel开发者_运维知识库f-descriptive, the item will automatically expire and removed from the list.
I couldn't imagine how to do that. Can anyone give me a clue?
If you're targeting .NET 4 or above, use the MemoryCache (or derive your custom implementation from ObjectCache).
Back before 4, if you wanted a cache in your app you could simply snag System.Web.Cache and use that in any .NET app. It didn't have any real dependencies on any "web" code, but it did require you reference System.Web.dll. It seemed odd (like referencing Microsoft.VisualBasic.dll from a C# app), but didn't actually affect your application negatively.
With the advent of the Client Profile, breaking dependencies between desktop-centric code and server-centric code became important. So the ObjectCache was introduced so that desktop app (not sure about silverlight, wp7) developers could break that dependency and be able to target just the client profile.
Just a quick example for the answer Will gave
Add reference to System.Runtime.Caching
MemoryCache cache = new MemoryCache("CacheName");
cache.Add(key, value, new CacheItemPolicy()
{ AbsoluteExpiration = DateTime.UtcNow.AddSeconds(20) });
You can then check if something is still in the cache by going
if (cache.Contains(key))
And if you want your cache to have a low time limit then you will need to change the refresh time of the cache with a nice little hack.
MemoryCache AbsoluteExpiration acting strange
you can also try something like this.
Create a custom class
public class Custom
{
string item; //will hold the item
Timer timer; //will hanlde the expiry
List<Custom> refofMainList; //will be used to remove the item once it is expired
public Custom(string yourItem, int milisec, List<Custom> refOfList)
{
refofMainList = refOfList;
item = yourItem;
timer = new Timer (milisec);
timer.Elapsed += new ElapsedEventHandler(Elapsed_Event);
timer.Start();
}
private void Elapsed_Event(object sender, ElapsedEventArgs e)
{
timer.Elapsed -= new ElapsedEventHandler(Elapsed_Event);
refofMainList.Remove(this);
}
}
Now you can create List<Custom>
and use it. It's items will be deleted once specified time is over.
You will need to create an object that can manage this.
Think about what it will need to store per item. Basically, the data (e.g. txtName
), and an expiry time. That means you probably will need a class or struct that just has those 2 elements.
Your ExpiringList
class will be a list of that type.
Now you have your basic data structure (a collection/list of ExpiringListItem
) you need to think about what operations you want to support. Currently you've listed AddToList, others would probably be RemoveFromList, Clear, and maybe iterating over all items.
The only thing unique to your ExpiringList compared to a normal List<T>
is that you want to automatically remove expired items. Therefore it would make sense to make your ExpiringList implement the interface IList<T>
and use a private List internally, possibly you could make your list (and by necessity your ExpiredListItem
class) generic.
The tricky part, beyond understanding and implementing inheritance (a separate question really), is working out how to remove expired items.
This would mean creating a method within your class that iterated (in reverse order) over your items, comparing their expiry time with the current time and removing expired ones.
You could implement the interface simply by calling the appropriate methods on your internal list.
You could say at this point, you're done, since you just call that method periodically to ensure sure all expired items are gone before you use the items in the list.
Maybe a better option would be to call this method before running the method on the internal list. Depending on how you will use your list this may be overkill.
@haris-hasan's solution is great, but this will be a bit costlier; at least for smaller collections. This can be achieved by writing a self managed class as below:
private class Candidates
{
private List<Collection> _lstCandidates = new List<Collection>();
/// <summary>
/// Inserts new Candidate into internal collection.
/// </summary>
/// <param name="strName">Name of the candidate</param>
/// <param name="dtExpiry">Expiry date when the entry will be kicked out</param>
public void Add(string strName, DateTime dtExpiry)
{
//To avoid duplicacy, this can be cahnged according to requirement.
if(_lstCandidates.Find(x=> x.CandidateName == strName) == null){
_lstCandidates.Add(new Collection(strName, dtExpiry));
}
else {
//Check expiry time and remove
}
}
/// <summary>
/// Returns candidate if Candidate name has not been expired yet.
/// </summary>
/// <param name="strName">Name of the candidate that was previously added into the collection</param>
/// <returns></returns>
public string Get(string strName)
{
//Find Candidate
Collection collection = _lstCandidates.Find(x => x.CandidateName == strName);
if(collection != null)
{
//If found then check expiry.
if(DateTime.Now.Subtract(collection.ExpiryDate).TotalSeconds >= 0)
{
//If expired then remove candidate and return null.
_lstCandidates.Remove(collection);
return null;
}
else
{
//return candidate name
return collection.CandidateName;
}
}
else
{
return null;
}
}
private class Collection
{
public string CandidateName { get; set; }
public DateTime ExpiryDate { get; set; }
public Collection(string CandidateName, DateTime ExpiryDate)
{
this.CandidateName = CandidateName;
this.ExpiryDate = ExpiryDate;
}
}
}
For smaller collections this is enough and will return only those entries that have not been expired yet. For larger collections this can be enhanced:
- By adding internal timer as suggested by @haris-hasan. This will definitely make it as an independent object.
- To save a "timer", a method can be added to kick out expired entries and that method can be called from any existing timer, on page load or before any api-call so that collection can be shrinked as soon as possible.
精彩评论