A Ready To Use Software Licensing Solution in C#

Introduction

First, I’d like to show you a live demo for this solution.

A Simple Example

I had a application haveing feature 1, 2 and 3,  and I want user to pay for each feature they like instead of paying for the whole package. So I designed a license solution to make this possible.

Current Solution

1) My application launches and finds itself not activated

2) It displays the activiation form and show the current device UID for purchasing a license

3) User shall give this device UID to our vendor to purchase the license, via either mail or phone.

4) At our vendor side, there is a license issuer program to issue the license based on the device UID and those features the user bought.

5) After license is generated, vendor shall paste the license string into a text file or mail to our user for activation.

6) User use paste the license string into the activiation form to activate the application.

Well, if this make you interested, please read on.

The highlights of this solution is:

  • digital signature technology is used to protect the license file
  • XML based license file allows it to contain rich information needed by the application
  • support both single license mode and volume license mode.
  • for single license mode, PC’s unique key is generated based on PC’s hardware. And BASE36 algorithm is used to generate the unique key for easier usage.

As I learnt, the key concept of such a license solution has been introduced years ago, even there are similar articles on CodeProject as well. However, it seems to be no ready-to-use solution or library out there. So it is a chance for me to do it!

Background

I was working on a project that is a system having many key features, which are expected to be actived or deactived based on the license provided. Boses want the feature on/off mechanism of the licensing system to be highly flexible, so the idea of pre-defined different editions is not suitable for this purpose.

The benefits is end user can just pay for those feature he/she want. E.g., user A can only pay for feature A, B & C; while user B only want feature A & C, and user C may only pay for feature B.

A good idea is to put those active features into a XML list and use this list as the license file. However, the next question is how to protect this license file since it is juat a plain text XML. Finally the digital signature solution answers the question.

Major Ideas

Main Workflow

The below chart describe the main workflow of this licensing solution:

Notes:

  1. End User Application generates the Unique ID for the current PC.
  2. Unique ID will be passed to License Issuer. This shall be a offline step which may include additional actions such as purchase and payment.
  3. License Issuer issue the license file based on the Unique ID and license options. I.e., decide to enable which features based on the purchase and payment.
  4. Send back the license file to end user. This is also a offline step, maybe by mails or USB drivers.
  5. End User Application verify the license file and startup.

Unique ID for the device

For now, this solution is only used on PC, also including servers & laptops. It has not been used in mobile devices yet. I think the algorithm to get unique ID for mobile devices shall be different. Here we just talk about PC first.

The unique ID for a PC contains 4 parts:

  • Application Name
  • Processor ID
  • Motherboard Serial Number
  • Disk Volume Serial Number of Drive C

The 4 parts are concatenated as strings, then checksum is generated via MD5. And BASE36 encoding is used to format the checksum into a string like “XXXX-XXXX-XXXX-XXXX” for easier reading and transferring.

/// <summary>
/// Combine CPU ID, Disk C Volume Serial Number and Motherboard Serial Number as device Id
/// </summary>
/// <returns></returns>
public static string GenerateUID(string appName)
{
    //Combine the IDs and get bytes
    string _id = string.Concat(appName, GetProcessorId(), GetMotherboardID(), GetDiskVolumeSerialNumber());
    byte[] _byteIds = Encoding.UTF8.GetBytes(_id);

    //Use MD5 to get the fixed length checksum of the ID string
    MD5CryptoServiceProvider _md5 = new MD5CryptoServiceProvider();
    byte[] _checksum = _md5.ComputeHash(_byteIds);

    //Convert checksum into 4 ulong parts and use BASE36 to encode both
    string _part1Id = BASE36.Encode(BitConverter.ToUInt32(_checksum, 0));
    string _part2Id = BASE36.Encode(BitConverter.ToUInt32(_checksum, 4));
    string _part3Id = BASE36.Encode(BitConverter.ToUInt32(_checksum, 8));
    string _part4Id = BASE36.Encode(BitConverter.ToUInt32(_checksum, 12));

    //Concat these 4 part into one string
    return string.Format("{0}-{1}-{2}-{3}", _part1Id, _part2Id, _part3Id, _part4Id);
}

XML based license file

So, in order to let the license file contain more information, a XML based license file is necessary. In C#, we can easily use XML Serializer to serialize the object into XML and vice verca.

The basic license entity is defined as below: (Some codes may contains Chinese, will do multiple language later)

public abstract class LicenseEntity
   {
       [Browsable(false)]
       [XmlIgnore]
       [ShowInLicenseInfo(false)]
       public string AppName { get; protected set; }

       [Browsable(false)]
       [XmlElement("UID")]
       [ShowInLicenseInfo(false)]
       public string UID { get; set; }

       [Browsable(false)]
       [XmlElement("Type")]
       [ShowInLicenseInfo(true, "Type", ShowInLicenseInfoAttribute.FormatType.EnumDescription)]
       public LicenseTypes Type { get; set; }

       [Browsable(false)]
       [XmlElement("CreateDateTime")]
       [ShowInLicenseInfo(true, "Creation Time", ShowInLicenseInfoAttribute.FormatType.DateTime)]
       public DateTime CreateDateTime { get; set; }

       public abstract LicenseStatus DoExtraValidation(out string validationMsg);

   }

It contains 3 default properties:

  • UID, which is the device’s unique ID (Used to identify the specified device for single license. Not used for volume license)
  • Type, indicate it is a single license or volume license
  • CreateDateTime, indicate when is the license created

Since this is an abstract class, you can just extend it for additional properties by inheriting it.

Protect the license file

OK, now we have the license file and enough information we need. The problem is that a XML file for licensing is very weak because anyone can modify it. Thus we need to introduce digital signature solution.

Generate a certificate

To use digital signature, first of all, we need a pair of RSA keys. Private key for system owner to sign the XML file. And the public key for end user’s application to verify the signed XML license file.

A easy way is to use “makecert” command to generate the certificates which we need to sign and verify the XML license file. Details will be covered in the later part of this article, please keep reading!

Sign the license file

C# provides native support for digital signature, so it is very easy to sign the XML license file as below: (These codes are copied from Microsoft samples)

// Sign an XML file.
// This document cannot be verified unless the verifying
// code has the key with which it was signed.
private static void SignXML(XmlDocument xmlDoc, RSA Key)
{
    // Check arguments.
    if (xmlDoc == null)
        throw new ArgumentException("xmlDoc");
    if (Key == null)
        throw new ArgumentException("Key");

    // Create a SignedXml object.
    SignedXml signedXml = new SignedXml(xmlDoc);

    // Add the key to the SignedXml document.
    signedXml.SigningKey = Key;

    // Create a reference to be signed.
    Reference reference = new Reference();
    reference.Uri = "";

    // Add an enveloped transformation to the reference.
    XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
    reference.AddTransform(env);

    // Add the reference to the SignedXml object.
    signedXml.AddReference(reference);

    // Compute the signature.
    signedXml.ComputeSignature();

    // Get the XML representation of the signature and save
    // it to an XmlElement object.
    XmlElement xmlDigitalSignature = signedXml.GetXml();

    // Append the element to the XML document.
    xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));

}

Now we are ready to publish the license for for end users. The last ‘optimization’ is to flat the XML so I encoded it with BASE64 and put all the output into a plain text file as the license.

Verify the license file

When the license file file is installed on the end user’s PC, the end user’s application shall populate the public key file and verify the license file using it.

// Verify the signature of an XML file against an asymmetric
// algorithm and return the result.
private static Boolean VerifyXml(XmlDocument Doc, RSA Key)
{
    // Check arguments.
    if (Doc == null)
        throw new ArgumentException("Doc");
    if (Key == null)
        throw new ArgumentException("Key");

    // Create a new SignedXml object and pass it
    // the XML document class.
    SignedXml signedXml = new SignedXml(Doc);

    // Find the "Signature" node and create a new
    // XmlNodeList object.
    XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");

    // Throw an exception if no signature was found.
    if (nodeList.Count <= 0)
    {
        throw new CryptographicException("Verification failed: No Signature was found in the document.");
    }

    // This example only supports one signature for
    // the entire XML document.  Throw an exception
    // if more than one signature was found.
    if (nodeList.Count >= 2)
    {
        throw new CryptographicException("Verification failed: More that one signature was found for the document.");
    }

    // Load the first <signature> node.
    signedXml.LoadXml((XmlElement)nodeList[0]);

    // Check the signature and return the result.
    return signedXml.CheckSignature(Key);
}

If the above verification is successful, the application starts to read the XML contents and can turn related features on/off accordingly.

About the Library

The whole .NET solution is built based on .NET Framework Version 4.0, in order to provide maximum compatibility even for retired Windows XP.

What I Have Provided

There are 5 projects inside this solution, which are split into 2 parts:

Core Libraries:

It contains 2 projects. One is QLicense which contains the core objects and logic. The other is ActivationControls4Win which contains the related Windows Form Controls for easy usage.

Demo: 

This part contains a demo application which uses the above license solution and a demo activation tool which issues the license.

What You Need To Do

Step by Step is here for how to use this library. I will use those demo projects as a sample to describ how to create your own application that integrats this license solution.

1. Create your certificates for your application

It is recommended that you create a new set of certificates for each of your new application, this is for security consideration.

1) You can just use makecert command to do this like:

makecert -pe -ss My -sr CurrentUser -$ commercial -n "CN=<YourCertName>" -sky Signature

Replace “<YourCertName>” with your own certificate name.

2) After executing the above command, open your Certificate Management window by runninig “certmgr.msc”.

3) Find the created certificate under “Personal” category with the name you specified in <YourAppName> above.

4) Right click on the certificate and select “All Tasks”->”Export”

5) On the Export dialogue, select “Yes, export the private key” and leave the other settings as default.

6) On the password diaglogue, input a password to protect the private key. You need to copy this password in your code when using this certificate. E.g., we use password “demo” here.

7) For the file name, we may use “LicenseSign.pfx” for this demo. Now we have the certificate with private key on hand.

8) Do step 4) to step 7) again to export the public key, just the difference is to choose “No, do not export the private key” and use file name as “LicenseVerify.cer” instead. Leave all the other options as default.

Well, we now have both the private key and public key generated for our solution.

2. Create your own license entity class – “DemoLicense”

1) You need to create a Class Library project which contains your own license entity, naming it “DemoLicense” for example.

2) Add Reference to QLicense library

3) Create a new class naming “MyLicense” and inherits “QLicense.LicenseEntity”

4) Add your own properties as you need

And the final codes shall look like:

using QLicense;
using System.ComponentModel;
using System.Xml.Serialization;

namespace DemoLicense
{
    public class MyLicense : QLicense.LicenseEntity
    {
        [DisplayName("Enable Feature 01")]
        [Category("License Options")]        
        [XmlElement("EnableFeature01")]
        [ShowInLicenseInfo(true, "Enable Feature 01", ShowInLicenseInfoAttribute.FormatType.String)]
        public bool EnableFeature01 { get; set; }

        [DisplayName("Enable Feature 02")]
        [Category("License Options")]        
        [XmlElement("EnableFeature02")]
        [ShowInLicenseInfo(true, "Enable Feature 02", ShowInLicenseInfoAttribute.FormatType.String)]
        public bool EnableFeature02 { get; set; }

        [DisplayName("Enable Feature 03")]
        [Category("License Options")]        
        [XmlElement("EnableFeature03")]
        [ShowInLicenseInfo(true, "Enable Feature 03", ShowInLicenseInfoAttribute.FormatType.String)]
        public bool EnableFeature03 { get; set; }        

        public override LicenseStatus DoExtraValidation(out string validationMsg)
        {
            //Here, there is no extra validation, just return license is valid
            validationMsg = string.Empty;
            return LicenseStatus.VALID;
        }
    }
}

Notes:

XmlElement attribute indicates the element name when the object is serilized into XML.

ShowInLicenseInfo attribute indicates whether this property shall be displayed in LicenseInfoControl which is a WinForm control contained in ActivationControls4Win project.

3. Integrate QLicense library with your application – “DemoWinFormApp”

1) Add Reference to DemoLicense, QLicense and ActivationControls4Win

2) Add LicenseVerify.cer generated in step 1 into the project, make it as Content and Copy to Output Directory If Newer in the file property settings.

3) Put the LicenseInfoControl from ActivationControls4Win onto the form you’d like to show license details, such as About form. For the demo, I just put it on the main form.

4) The main logic for the main form is to validate the license and inform user to activate the application if needed. I put the logic in Form_Shown event in order to let main form shown in the backgound for better user experience. You may put these logic into a splash form or other place.

private void frmMain_Shown(object sender, EventArgs e)

{
    //Initialize variables with default values
    MyLicense _lic = null;
    string _msg = string.Empty;
    LicenseStatus _status = LicenseStatus.UNDEFINED;

    //Check if the XML license file exists
    if (File.Exists("license.lic"))
    {
        _lic = (MyLicense)LicenseHandler.ParseLicenseFromBASE64String(typeof(MyLicense), File.ReadAllText("license.lic"), "LicenseVerify.cer", out _status, out _msg);
    }
    else
    {
        _status = LicenseStatus.INVALID;
        _msg = "Your copy of this application is not activated";
    }

    switch (_status)
    {
        case LicenseStatus.VALID:

            //TODO: If license is valid, you can do extra checking here
            //TODO: E.g., check license expiry date if you have added expiry date property to your license entity
            //TODO: Also, you can set feature switch here based on the different properties you added to your license entity

            //Here for demo, just show the license information and RETURN without additional checking
            licInfo.ShowLicenseInfo(_lic);

            return;

        default:
            //for the other status of license file, show the warning message
            //and also popup the activation form for user to activate your application
            MessageBox.Show(_msg, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Warning);

            using (frmActivation frm = new frmActivation())
            {
                frm.ShowDialog();

                //Exit the application after activation to reload the license file
                //Actually it is not nessessary, you may just call the API to reload the license file
                //Here just simplied the demo process

                Application.Exit();
            }
            break;
    }
}

4) Add a new form named frmActivation and put LicenseActivateControl from ActivationControls4Win onto it. This is the form user need to enter license content and activate your application.

5) Here is the main logic for frmActivation. It will display the calculated device UID once the form popup:

private void btnCancel_Click(object sender, EventArgs e)
       {
           if (MessageBox.Show("Are you sure to cancel?", string.Empty, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
           {
               this.Close();
           }
       }

       private void frmActivation_Load(object sender, EventArgs e)
       {
           //Assign the application information values to the license control
           licActCtrl.AppName = "DemoWinFormApp";
           licActCtrl.LicenseObjectType = typeof(DemoLicense.MyLicense);
           licActCtrl.CertificatePublicKeyFilePath = Path.Combine(Application.StartupPath, "LicenseVerify.cer");
           //Display the device unique ID
           licActCtrl.ShowUID();
       }

       private void btnOK_Click(object sender, EventArgs e)
       {
           //Call license control to validate the license string
           if (licActCtrl.ValidateLicense())
           {
               //If license if valid, save the license string into a local file
               File.WriteAllText(Path.Combine(Application.StartupPath, "license.lic"), licActCtrl.LicenseBASE64String);

               MessageBox.Show("License accepted, the application will be close. Please restart it later", string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Information);

               this.Close();
           }
       }

4. Create your license issuer tool – “DemoActivationTool”

1) Create a new Windows Form Application project, naming “DemoActivationTool”.

2) Add References to DemoLicense, QLicense and ActivationControls4Win

3) Add LicenseSign.pfx generated in step 1 into the project, make it as Content and Copy to Output Directory If Newer in the file property settings.

4) Draw the control LicenseSettingsControl and LicenseStringContainer on the main form, it may look like:

5) Add the following codes for main form. Details are explains inline with the codes as comments below:

public partial class frmMain : Form
{
    private const string CERT_PWD = "demo";
    private const string CERT_NAME = "LicenseSign.pfx";

    public frmMain()
    {
        InitializeComponent();
    }

    private void frmMain_Load(object sender, EventArgs e)
    {
        //Initialize the path for the certificate to sign the XML license file
        licSettings.CertificatePrivateKeyFilePath = Path.Combine(Application.StartupPath, CERT_NAME);
        licSettings.CertificatePassword = CERT_PWD;

        //Initialize a new license object
        licSettings.License = new MyLicense();
    }

    private void licSettings_OnLicenseGenerated(object sender, QLicense.Windows.Controls.LicenseGeneratedEventArgs e)
    {
        //Event raised when license string is generated. Just show it in the text box
        licString.LicenseString = e.LicenseBASE64String;
    }

    private void btnGenSvrMgmLic_Click(object sender, EventArgs e)
    {
        //Event raised when "Generate License" button is clicked.
        //Call the core library to generate the license
        licString.LicenseString = LicenseHandler.GenerateLicenseBASE64String(
            new MyLicense(),
            Path.Combine(Application.StartupPath, CERT_NAME),
            CERT_PWD);
    }

}

 

LINK: http://www.codeproject.com/Articles/996001/A-Ready-To-Use-Software-Licensing-Solution-in-Csha

Speech recognition, speech to text, text to speech, and speech synthesis in C#

Some content on this page was disabled on December 28, 2015 as a result of a DMCA takedown notice from CodeProject Solutions Inc.. You can learn more about the DMCA here:

https://en.support.wordpress.com/copyright-and-the-dmca/

Cache: A threadsafe, Simple, Efficient, Generic In-memory Cache

Introduction

Today, I want to discuss the “caching” topic and show you my implementation of a generic memory cache,Cache<K,T>. You will find my full implementation documented here and as download, including some simple unit tests for demonstration.


Update: The original article had the class named Cache<T> with only generic contents of the cache. It has been extended, to allow Cache<K,T> to allow you to specify the type of the key of the cache too. Cache<T> is still available, with no change! It just derives from Cache<K,T> as:

public class Cache<T> : Cache<string, T>

Update 2: With credits to @Kochise, I added two new methods to the Cache class:

Clear() and AddOrUpdate(K, T) with a default lifetime of Timeout.Infinite. Thanks for those ideas, Kochise Smile | :) . This brought me to the idea, to implement a Remove() method that takes a keyPattern as aPredicate<K>, so you can remove multiple entries from the cache with a single call. You can find detailed explanations below in the “Using the Code” section.

Both zip files in the download have been updated. The LoadTest had a strange behavior in Release mode due to optimization. This is fixed. I also updated the unit tests contained in Cache.zip to call the new Clear() method and the new Remove() method.


I wrote my first object cache back in 2005, when .NET 2.0 arrived. This is (more or less Smile | :) ) still the same class, it grew up over the years, uses Threading Timers (that utilize the ThreadPool) now, is thread-safe and recently I updated it to C# 6.0 syntax.

The reason why I write this down today for you is a discussion I had with a fellow colleague, why I don’t use theMemoryCache class, which ships with .NET Framework anyway. Well, one reason for sure is, that I “just got used to the interface of my own cache”, but another one (and at least as important as my first reason) is:MemoryCache has an ugly interface. I don’t like it.

What I like, when I see a class? A simple, straightforward interface. When I want to cache an object, or better: an item of type T, I want to see:

  • How can I add/update it and for how long is it stored?
  • How can I access (Get) it?
  • How can I remove it?
  • And sometimes: Does it already exist?

What I do *not* want to see:

  • Use a CacheItemPolicy, DateTimeOffsets, different strategies, expirations,… tons of sub-classes and sub-structures
  • A documentation several pages long on the website.

Unfortunately, all this happens, when you look up the MemoryCache class on MSDN (https://msdn.microsoft.com/de-de/library/system.runtime.caching.memorycache(v=vs.110).aspx).

If you think the same way than me, if you prefer a simple and easy-to-use interface without distractions, you probably will like this class.

I have never been a fan of the MemoryCache because it puts lots of overhead on my shoulders. Things I do not want to think about.

Next thing, I didn’t like about MemoryCache: It is not generic. It works with object.

Background

Caching in memory makes sense in many situations. Be it results of database queries that might run in high frequency, or be it reflection, and many more.

Especially reflection is such a thing… You load an Assembly, get the Types, the Interfaces, maybe look for Attributes, find some MethodInfos that you want to Invoke later… Why scan through the Assembly over and over again? Just keep the MethodInfo you want to invoke in a cache, give it a unique Key and then call it, whenever you need it. Eliminate the Reflection cost. Do it only once. Yes, of course you could create a private Dictionary and store your MethodInfo objects there. But you then have to take care about thread safety, handle exist/replace and all those things, that this Cache implementation already does for you. So, from my point of view, it’s fine to use the “Cache” for storing item<T> for the process lifetime, because all the surrounding noise is handled and encapsulated there for you.

Next good option is the local caching of database query results. A Cache<DataTable> doesn’t make much sense, you say? Because the DB Server has its own cache anyway? Well, right, it has. And it does caching. But in a larger scale, say, 2000 clients or even more (I am working on a 50k client system in my job at the moment), it makes a huge difference for the DB cluster. 50k queries that use the DB cache still make 50k requests to the DB cluster! If most of them can be handled by a local Cache<DataTable>, you take away a real pain, a huge load from the DB.

So your local client can refresh “at will”, every second or every 3 seconds to get some status – if you are in a polling scenario – and you can define in your business logic or data layer, far away from the GUI client layer, how often the client will be presented new data, by just setting a single value: the cache time. And all this happens local, the DB doesn’t know anything about it and doesn’t need to care.

Many of my applications utilize many different instances of this Cache, some keeping entries only for a few seconds, some keeping entries for the lifetime of the process (many Reflection scenarios do this).

So, let’s take a look at my generic cache, shall we?

Using the Code

As I said at the beginning of this article, I like a clean and straightforward interface, when I look at a class.

The Cache<T> class looks like this:

It is reduced to what you really *need*: Add(Update), (Try)Get, Remove, Exist and Clear. For convenience, there is also an Indexer implemented, so you can Get() a Cache-Entry with:

cache.Get(key);
or
cache[key];

whatever you prefer more.

Let’s start with the basics of the Cache class. The downloadable file contains three classes:

Cache : Cache<object>
Cache<T> : Cache<string, T>
Cache<K,T>

The non-generic Cache class just implements a plain object cache if you need to store objects of different types in a single cache instance.

A personal recommendation: If you only have 2 or 3 different types you want to cache (which will be true for the vast majority of use cases), it is a better and cleaner approach to create 2 or 3 Cache<T> instances than a singleCache<object>. There are no background threads involved, the timers use ThreadPool threads when they fire, so there is no real reason to stick to one single Cache instance. Please keep that in mind.

What does the class do, and what does it *not* do:

  • It caches objects based on second-intervals, not milliseconds.
  • It supports Timeout.Infinite to keep items forever (= process lifetime).
  • It is IDisposable.
  • It is thread-safe.
  • It is generic.
  • Cache expiration uses System.Threading.Timers Timer, which utilizes ThreadPool Threads when doing the callbacks for expiration, so you don’t have a ton of inactive sleeper threads hanging around when your cache gets bigger or when you have multiple instances of the Cache running.

What it does not do:

  • Offer monitoring, listing, iteration, examination of the contents.
  • Different strategies and ways to expire items. Either you want it in the cache or not. If not, .Remove it.
  • Offer events to react on an item before it gets purged.
  • Maximum memory settings and such things. The responsibility of how much you put into the cache is up to you.

Let’s start with a little demo.

I will show the demo by some unit testing code, because it explains very clean, how to use the class.

[TestMethod]
public void Cache_Generic_Expiration_Ok()
{
    // Create a cache to hold DataTables
    Cache<DataTable> cache = new Cache<DataTable>();

    DataTable testTable = new DataTable();

    // Add a DataTable with the key "test" to the cache, for 1 second
    c.AddOrUpdate("test", testTable, 1);

    // Check, whether the cache entry "test" exists.
    Assert.IsTrue(c.Exists("test"));

    // Check the references of our local table and the entry from the cache...
    Assert.AreSame(c.Get("test"), testTable);

    // Now wait a little more than a second to give the cache time to expire...
    Thread.Sleep(1050);

    // Now the entry no longer exists.
    Assert.IsFalse(c.Exists("test"));
}

Those few lines of code already explain the most important things you need to know about the class. Just create an instance – no complicated threading, no noise.

AddOrUpdate an item to put it to the cache. The third parameter is the cache time. Specify Timeout.Infinitehere to keep it forever.

Exists tells you whether a specific key already exists in the cache.

Remove removes an item from the Cache.

Get(key), TryGet(key, out T item) or [key] returns you the item from the cache or default(T), if it is not found. No exception is raised, if the item does not exist. Why? Because it does not really make a difference. The normal use case is a code construct like this:

(This has been taken from a data layer I wrote, using the cache, implicit null check and query execution, if null).

result.Data = sqlCache[commandKey] ?? ExecuteQuery(command);
sqlCache.AddOrUpdate(commandKey, result.Data, cacheTime);

Here would not be a benefit from an Exception. If you really want to behave completely different, if an item is currently not cached, use TryGet or Exists.

If you looked at these two lines closely, you might say now: “Wait! If you update this entry with cacheTimeagain, the entry will never expire! This is wrong!”.

The thing here is: The AddOrUpdate has a fourth (optional) parameter which defaults to false. It’s name isrestartTimerIfExists. This parameter gives you full control over the cache entry. By default, the timer is not modified (and the cacheTime parameter is ignored if you only update an entry), so updating an entry just updates the contents of the entry, not it’s TTL (Time to live). The control (and therefore, the decision), whether you want to reset the timer to a new value, it totally up to you, depending on the situation/reason why you just updated the entry.

Removing items from the cache is worth a closer look, as it offers a neat little signature to bulk-remove items that fulfill a certain condition.
The Remove-method offers two signatures:

Remove(K key)
and
Remove(Predicate<K> keyPattern)

The second one allows you to specify any predicate (like a Lambda expression) that has to evaluate to true for each key you want to remove from the cache.
One of the unit tests demonstrates this very well (look at the c.Remove line in the middle of the test):

[TestMethod]
public void Cache_Remove_By_Pattern_Ok()
{
    Cache c = new Cache();
    c.AddOrUpdate("test1", new object());
    c.AddOrUpdate("test2", new object());
    c.AddOrUpdate("test3", new object());
    c.AddOrUpdate("Other", new object());
    Assert.IsTrue(c.Exists("test1"));
    Assert.IsTrue(c.Exists("Other"));

    c.Remove(k => k.StartsWith("test")); // <-- This one here 🙂

    Assert.IsFalse(c.Exists("test1"));
    Assert.IsFalse(c.Exists("test2"));
    Assert.IsFalse(c.Exists("test3"));
    Assert.IsTrue(c.Exists("Other"));
}

As you can see, any Lambda can be used to remove multiple items. If you build your cache keys by a specific pattern, no matter whether they are int or string keys (or any other type), you can wipe sections of the cache with a single call.

Let me give you a simple example, so you get the idea:
I take an ImageCache as an example as this is quite a common use case:
Your keys are built like [content].[userid] to have them unique:

UserPortrait.356
?UserPortrait.409
?UserPortrait.1158
?UserPortrait.22
Avatar.869
Avatar.223
Avatar.127
Avatar.256
Avatar.1987

So it is easy for you to wipe all Avatar Images from your cache by calling:

Remove(k => k.StartsWith("Avatar."));

but you can also remove all images for a specified [userid] with:

Remove(k => k.EndsWith($".{userid}");

That’s all for the usage of the class! Add, Remove, Get and one or two little convenience methods. Clean and simple!

The Source Code of Cache<K,T>

Now I want to show and discuss the source code of the Cache<T> class. It’s quite simple, no big magic here, but I find it important in an article to do a look “behind the scenes” and explain, what’s going on.

Constructing a Cache<T>

All Cache implementations only have one single, default constructor with no parameters.

Cache<DataTable> sqlCache = new Cache<DataTable>();

Internal data storage is done in two simple Dictionaries. Yes I could’ve used just one Dictionary, but as theTimers can be more or less reset and handled independently from the cached objects, two Dictionaries are fine.

Thread safety is achieved with a ReaderWriterLockSlim that handles parallel access.

public class Cache<K, T> : IDisposable
{
    #region Constructor and class members
    /// <summary>
    /// Initializes a new instance of the <see cref="Cache{K,T}"/> class.
    /// </summary>
    public Cache() { }

    private Dictionary<K, T> cache = new Dictionary<K, T>();
    private Dictionary<K, Timer> timers = new Dictionary<K, Timer>();
    private ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
    #endregion

The IDisposable implementation is completely standard, so I will not discuss it here in detail and instead jump to the more interesting parts of the class.

Add, Remove, Get and Exist

These methods are your interface to work with the Cache<T>.

AddOrUpdate:

public void AddOrUpdate(K key, T cacheObject, int cacheTimeout, bool restartTimerIfExists = false)
{
    if (disposed) return;

    if (cacheTimeout != Timeout.Infinite && cacheTimeout < 1))
        throw new ArgumentOutOfRangeException("cacheTimeout must be greater than zero.");

    locker.EnterWriteLock();
    try
    {
        CheckTimer(key, cacheTimeout, restartTimerIfExists);

        if (!cache.ContainsKey(key))
            cache.Add(key, cacheObject);
        else
            cache[key] = cacheObject;
    }
    finally { locker.ExitWriteLock(); }
}

What happens in AddOrUpdate?

  • If we are disposed, no more access
  • Parameter value check
  • In a write lock:
    • A check of the timer (more on that later)
    • Simple Add/Replace of the cacheObject in the Dictionary

As promised, not much magic here Smile | :) .

Remove

public void Remove(K key)
{
    if (disposed) return;

    locker.EnterWriteLock();
    try
    {
        if (cache.ContainsKey(key))
        {
            try { timers[key].Dispose(); }
            catch { }
            timers.Remove(key);
            cache.Remove(key);
        }
    }
    finally { locker.ExitWriteLock(); }

Remove is simple, too. Just a write-lock-safe Remove of both entries, the timer and the cached object.
The second signature of Remove allows a Predicate<K> to be specified to find the key(s) to remove:

public void Remove(Predicate<K> keyPattern)
{
    if (disposed) return;

    locker.EnterWriteLock();
    try
    {
        var removers = (from k in cache.Keys.Cast<K>()
                        where keyPattern(k)
                        select k).ToList();

        foreach (K workKey in removers)
        {
            try { timers[workKey].Dispose(); }
            catch { }
            timers.Remove(workKey);
            cache.Remove(workKey);
        }
    }
    finally { locker.ExitWriteLock(); }
}

The Linq that fills my var removers must use a .ToList() as it is not allowed to modify a collection while iterating through it. The predicate is only used here in the where clause and must evaluate to true for each key that shall be removed.

Get

/// <summary>
/// Gets the cache entry with the specified key or return <c>default(T)</c>
/// if the key is not found.
/// </summary>
/// <param name="key">The cache-key to retrieve.</param>
/// <returns>The object from the cache or <c>default(T)</c>, if not found.</returns>
public T Get(K key)
{
    if (disposed) return default(T);

    locker.EnterReadLock();
    try
    {
        T rv;
        return (cache.TryGetValue(key, out rv) ? rv : default(T));
    }
    finally { locker.ExitReadLock(); }
}

/// <summary>
/// Tries to gets the cache entry with the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="value">(out) The value,
/// if found, or <c>default(T)</c>, if not.</param>
/// <returns><c>True</c>, if <c>key</c> exists,
/// otherwise <c>false</c>.</returns>
public bool TryGet(K key, out T value)
{
    if (disposed)
    {
        value = default(T);
        return false;
    }

    locker.EnterReadLock();
    try
    {
        return cache.TryGetValue(key, out value);
    }
    finally { locker.ExitReadLock(); }
}

In the Get method, you can see the reason, why I took a ReaderWriterLockSlim over a simple lock()statement. In case, you don’t know it: A lock() is always a write-lock and therefore a lock()ed block can only be entered sequential, one thread after the other, while a ReadLock as shown here can be processed parallel by multiple threads.

When a thread requests a WriteLock, this WriteLock has to wait, until the current readers have finished, then the WriteLock runs exclusive, like a lock() statement (all readers have to wait until write is finished). When the WriteLock is done, all readers may continue.

Exists

public bool Exists(K key)
{
    if (disposed) return false;

    locker.EnterReadLock();
    try
    {
        return cache.ContainsKey(key);
    }
    finally { locker.ExitReadLock(); }
}

Exists plain and simple returns, whether a specific entry is contained in the internal Dictionary.

Clear

public void Clear()
{
    locker.EnterWriteLock();
    try
    {
        try
        {
            foreach (Timer t in timers.Values)
                t.Dispose();
        }
        catch
        { }

        timers.Clear();
        cache.Clear();
    }
    finally { locker.ExitWriteLock(); }
}

Clear takes care that all pending timers are .Dispose()d before both Dictionaries are cleared.

Timer Check / Timer Callback

Let’s take a look at how the timing (TTL) of a cache entry is handled in Cache<T> and how therestartTimerIfExists flag is processed.

Code first Smile | :)

#region CheckTimer
// Checks whether a specific timer already exists and adds a new one, if not
private void CheckTimer(K key, int cacheTimeout, bool restartTimerIfExists)
{
    Timer timer;

    if (timers.TryGetValue(key, out timer))
    {
        if (restartTimerIfExists)
        {
            timer.Change(
                (cacheTimeout == Timeout.Infinite ? Timeout.Infinite : cacheTimeout * 1000),
                Timeout.Infinite);
        }
    }
    else
        timers.Add(
            key,
            new Timer(
                new TimerCallback(RemoveByTimer),
                key,
                (cacheTimeout == Timeout.Infinite ? Timeout.Infinite : cacheTimeout * 1000),
                Timeout.Infinite));
}

private void RemoveByTimer(object state)
{
    Remove((K)state);
}
#endregion

First, I check whether a Timer for this cache entry exists. It is possible that none exists, when this entry is currently added, and not updated.

If the Timer exists, it gets modified, if the restartTimerIfExists is set to true, otherwise it is left alone.

The parameters supplied to the timer are:

  • When adding:
    • The callback (RemoveByTimer) to be invoked when dueTime expires
    • The key of the cache entry (this is the state parameter of the callback method and my key to find the cache entry to remove)
    • The dueTime (time to wait before calling the callback method)
    • The period. This is always Timeout.Infinite in this class, as each entry can be removed only once.
  • When updating/changing:
    • The same two dueTime and period parameters as supplied, when adding, just with new values.

The RemoveByTimer method simply calls the (thread safe) Remove method of the Cache<T> class.

The non-generic Cache : Cache<object> class

Last but not least, I want to show you the more-than-simple code behind the non-generic version, Cache class:

public class Cache : Cache<object>
{
    #region Static Global Cache instance
    private static Lazy<Cache> global = new Lazy<Cache>();
    /// <summary>
    /// Gets the global shared cache instance valid for the entire process.
    /// </summary>
    /// <value>
    /// The global shared cache instance.
    /// </value>
    public static Cache Global => global.Value;
    #endregion
}

This class is a Cache<object> that can store any type of item and is used in highly mixed scenarios, with all the drawbacks object brings to the field.

Only interesting thing to mention is the Lazy initialization of the static Global member.

I always try to support as many scenarios as possible, and I can imagine that there are cases where you don’t want to instantiate your own cache instance (maybe you are too lazy Smile | :) ), so this class even provides a static Global cache member.

Performance

In the comments, there were some concerns about the performance of the cache. That’s why I want to make clear again, this is a local cache, not a server cache for a webserver that handles 50k clients in parallel access! It is made for your frontend applications or maybe your business/data layer.

We use it in a professional environment without any problems.

You can download the load test and test the cache on your local machine and compare your values to mine.

My test ran on a Lenovo Y50 Quad-Core (8 logical cores) Gaming Notebook with 16GB of RAM.

These are the results of my local load tests:

Cache<T> load test.
===================

1: Single threaded tests
1.1: Adding 1 Million entries.
     <K,T> = <long, string*32>
     Performance: 492/ms
-
1.2: 1 Million random Get calls
     Performance: 4166/ms
-
1.3: Removing 1 Million entries (with exists check)
     Performance: 3623/ms
-
2: Multi threaded tests
2.1: Adding 1 Million entries.
     Threads: 100, each adds 10k
     <K,T> = <long, string*32>
     Performance: 355/ms
-
2.2: 1 Million random Get calls
     Threads: 100, each adds 10k
     <K,T> = <long, string*32>
     Performance: 3937/ms
-
2.3: Removing 1 Million entries (with exists check)
     Threads: 100, each removes 10k
     <K,T> = <long, string*32>
     Performance: 1689/ms
-

 --- End of test ---

I will copy my explanation of this test from the comment I gave one member:

  • In a single threaded scenario (maybe when used only as a reflection cache or as database query result cache for a GUI app), I can add an entry in ~2 microseconds to a range of 1 million entries (which GUI app caches 1 million different queries or 1 million reflections?)

On the loaded cache, there are more than 4000 get requests per millisecond, or 4 per microsend or 1 access in less than 250 nanoseconds.
Remove is almost as fast as Get.

Then, with a thread load of 100 threads (again, this is not a server cache for thousands of parallel access requests – and even those run full parallel due to readlocks – only thousands of parallel Adds might slow down).

So the threaded tests result in:

  • A drop from 492 to 355 Adds per millisecond which still ends up in only 3 microseconds per add.
  • Get requests show almost equal performance (3930:4160) due to the read locks
  • Removing drops down in performance, agreed, losing about 50% but still in the area of nanoseconds per remove.

This performs very well even in a scenario with 100 parallel threads which is more than the average frontend application will use.

LINK: http://www.codeproject.com/Articles/1033606/Cache-T-A-threadsafe-Simple-Efficient-Generic-In-m

 

Honda Air Blade và Yamaha Nouvo: Cuộc chiến không hồi kết

Không hẹn mà gặp, cả Honda và Yamaha đều tung ra thị trường phiên bản mới của Air Blade và Nouvo cùng lúc.

Trên thị trường xe tay ga Việt Nam, từ lâu Honda Air Blade và Yamaha Nouvo là đối thủ truyền kiếp của nhau. Hai mẫu xe này cũng là những sản phẩm chủ lực của từng hãng. Chính vì vậy, mỗi chiếc đều được trang bị những thế mạnh riêng để cạnh tranh với đối thủ, đồng thời thường xuyên được nâng cấp, dù chỉ là những thay đổi nhỏ.

Yamaha Nouvo có mặt tại Việt Nam từ khoảng đầu những năm 2000. Trong khi đó, Honda Air Blade xuất hiện trên thị trường chậm hơn khoảng 6 năm. Tính đến thời điểm hiện tại, cả 2 mẫu xe đều có nhiều phiên bản khác nhau sau rất nhiều đời nâng cấp.

Yamaha Nouvo Fi thế hệ mới nhất ra mắt cách đây khoảng 1 năm. Ảnh: Hạ Phong
Yamaha Nouvo Fi thế hệ mới nhất ra mắt cách đây khoảng một năm. Ảnh: Hạ Phong.

Ở thế hệ mới nhất ra mắt cuối tháng 11 năm nay, Air Blade đã được cải tiến khá nhiều, sau khoảng 3 năm chỉ đổi màu sơn, tem xe. Air Blade 2016 mang kiểu dáng trẻ trung, thể thao, trái ngược hoàn toàn với phong cách trung tính Honda vẫn theo đuổi trước đây. Sự chuyển mình này có thể xem là để đối đầu trực diện với Yamaha Nouvo, dù thực tế trước đó Air Blade vẫn có doanh số bán tốt hơn so với đối thủ.

Sự thay đổi về ngoại hình có thể coi là bước chuyển mình để Air Blade nhắm thẳng đến những khách hàng trẻ tuổi thay vì phục vụ số đông như trước đây. Ngoài ra, Honda cũng nâng cấp nhẹ cho động cơ 125 phân khối của xe, khi tăng công suất lên mức 8,4 kW thay vì 8,2 kW như trước. Air Blade 2016 cũng là mẫu xe đầu tiên trong phân khúc sử dụng đèn pha LED.

Kiểu dáng thể thao trên Air Blade mới ra mắt. Ảnh: Anh Nguyễn.
Kiểu dáng thể thao trên Air Blade mới ra mắt. Ảnh: Anh Nguyễn.

Chỉ vài ngày sau khi Air Blade có phiên bản mới, Yamaha cũng mang sự thay đổi đến Nouvo. Tuy nhiên, đây chỉ là sự làm mới nhỏ về cách phối màu sơn và tem xe, bởi thế hệ hiện tại của Nouvo mới ra mắt cách đây khoảng một năm.

Phong cách thể thao thường gắn liền với Yamaha, từ kiểu dáng cho đến cách phối màu sơn và tem. Đó là điều không lạ, bởi các sản phẩm dành cho nam giới của liên doanh xe máy này đều lấy cảm hứng thiết kế theo DNA thể thao xuyên suốt của họ. Chính vì vậy, Nouvo về sau sở hữu kiểu dáng góc cạnh, trẻ trung. Dòng xe này thường được đánh giá cao hơn về mặt thẩm mỹ và phù hợp với khách hàng trẻ hơn so với Air Blade của Honda.

Mặt khác, theo đánh giá của số đông người sử dụng, Yamaha Nouvo sở hữu khả năng vận hành bốc, có tính thể thao cao hơn so với đối thủ. Mẫu xe tay ga này cũng đi tiên phong trong việc sử dụng đèn pha projector cho xe, một trang bị mang lại nhiều thích thú với người sử dụng. Phiên bản mới nhất của Nouvo duy trì đặc tính thể thao và thêm một số tiện ích cho người dùng. Tuy nhiên, những thay đổi kể trên của Air Blade 2016 sẽ khiến sự so sánh trở nên cân bằng hơn.

Cách phối màu sơn mới trên Yamaha Nouvo Fi. Ảnh: Yamaha
Cách phối màu sơn mới trên Yamaha Nouvo Fi. Ảnh: Yamaha.

Một yếu tố khác sẽ khiến người dùng cân nhắc khi lựa chọn giữa Honda Air Blade và Yamaha Nouvo là giá bán. Cùng mang phong cách thể thao và có những điểm khác biệt riêng, hai mẫu xe này có giá bán chênh lệch nhau khá nhiều. Phiên bản thấp nhất của Air Blade 125 có giá 37,9 triệu đồng, cao nhất 40,9 triệu đồng. Trong khi đó, Nouvo phiên bản thấp nhất có giá 33,9 triệu đồng, cao nhất 36,5 triệu đồng. Hơn thế nữa, trong thời điểm mới ra mắt, sản phẩm của Honda thường có tình trạng bị các đại lý đẩy giá lên cao hơn so với giá trị thực của sản phẩm.

Trong thời gian sắp tới, việc tung ra một phiên bản nâng cấp, cải tiến toàn diện cho Nouvo là điều có thể dự đoán, bởi mẫu xe này vẫn chưa được trang bị động cơ Blue Core tiên tiến nhất của Yamaha, đồng thời đối thủ vừa có bước chuyển mình về thiết kế. Cuộc chiến giữa 2 mẫu xe này, vì vậy, vẫn chưa hẹn hồi kết.

LINK: http://news.zing.vn/Honda-Air-Blade-va-Yamaha-Nouvo-Cuoc-chien-khong-hoi-ket-post606253.html

Export dữ liệu từ C# sang Excel.

Chào mọi người.
Hôm nay mình sẽ chia sẻ 1 tool export dữ liệu từ 1 List trong C# sang Excel rất đơn giản và nhanh
Chi tiết: http://1drv.ms/1TrxiT7
Hiệu năng khi export test trên máy mình với dữ liệu tự sinh.
– 100 records: 503 ms
– 1000 records: 991 ms
– 10000 records: 6276 ms
– 100000 records: 52787 ms