Sức khỏe

Hôm nay lướt web thấy đoạn thơ này hay phết, post lên đây chia sẻ.

“Làm trai cho đáng nên trai
Lên giường với vợ, nhớ bài sau đây
Thứ nhất phải tắm sạch ngay
Phụ nữ ghét nhất những tay hôi rình
Hai là phải nhớ chung tình
Phụ nữ ghét nhất là tình tay ba
Ba là không được kể ra
Cô này. cô nọ hôm qua thích mình
Bốn là luôn khen vợ xinh
Năm là luôn biết giữ mình… không say
Sáu là luyện tập hàng ngày
“Yêu” thật sang tạo … được ngay điểm mười!”

Advertisements

15 Best ASP.NET based Content Management Systems(CMS)

ASP.NET is a Web Application development framework thats lets the developers to build dynamic web applications using .NET.

In this article , we share links to 15 cool ASP.NET MVC based CMS (Content Management Systems).

15 Best ASP.NET based Content Management Systems(CMS)

LINK Gốc: http://abundantcode.com/15-best-asp-net-based-content-management-systemscms/

Five Great .NET Framework 4.5 Features

Table of contents

Introduction

It has been almost a year since .NET 4.5 got released. But the problems with most of the recent Microsoft releases have been communication with .NET developers. Only one or two features are known to developers and other features just stay on MSDN and end up becoming simple documents.

For example, the time you ask a .NET developer what is new in the core framework .NET 4.5 most of them will just sayasync and awaitt (at least with people whom I have interacted have just talked about those features).

Again it’s very difficult to run through all the new features. Because the features may not sound interesting depending on what you are working currently on..

So in this article I have picked my five favorite features introduced in .NET 4.5 core. Again it’s possible my favorites cannot be your favorites. But what I have done is while choosing these features I kept in mind the larger .NET community and I hope I have met that expectation.

Note: This article does not discuss the new features in ASP.NET, WCF, WPF, WWF etc. It only talks about new features related to the core.

Feature 1: async and await (code markers)

This feature has been oversold and every .NET evangelist has talked about it. But this is still my favorite and you will come to know why in a few lines from here.

async and await are markers which mark code positions from where control should resume after a task (thread) completes.

Let us try to make sense of the above statement by understanding the below code. If you see the flow of the below code:

  1. Method() gets called from the Static void main() entry point.
  2. Method() spawns a Task (thread) LongTask which waits for 10 seconds.
  3. At the same time the control comes back to Method() to execute the remaining code after the task was called. In other words as the invocation is multi-threaded (Task.Run…),  LongTask is also running i.e., waiting for 10 seconds and the remaining code of your Method() is also executed.

Now in certain scenarios we want step 3 to behave differently. We want that after LongTask() finishes execution, the control should go back to Method to execute the remaining code. The async and await keywords help to achieve the above behavior.

Now there are three important points to remember about the async and await keywords:

  1. async and await are pair keywords. You cannot use them in a standalone manner.
  2. async is marked on a method. This keyword is just an indicator saying that this method will have the awaitkeyword.
  3. The await keyword marks the position from where the task should resume. So you will always find this keyword in conjunction with Task.

Below is a modified version of the previously discussed code where we have applied async and await. All the other steps remain the same but “Step 3” is executed after “Step 2” completes. In simple words the control comes back toMethod() after the task has finished operation.

Now that you have read about “async” and “await”, let me put a cross question. The above behavior can be also achieved by using Task.Wait or Task.ContinueWith, so how do they differ? I am leaving this question as a home work for you.

Feature 2: Zip facility (Zip compression)

Zip is one of the most accepted archive file formats. Zip format is supported in almost all operating systems with some built-in name.

  • In Windows operating system it’s implemented by the name “Compressed folders”.
  • In MAC OS it’s implemented by the name “Archive utility”.

Now in .NET we did not have built-in support for implementing Zip compression. Many developers where using third party components like “DotnetZip”. In .NET 4.5, the Zip feature is baked in the framework itself, inside the namespaceSystem.IO.Compression.

The first step is you need to reference two namespaces:

  • System.IO.Compression.FileSystem
  • System.IO.Compression

The next step is to import the below two namespaces:

 Collapse | Copy Code
using System.IO.Compression;

If you want to Zip files from a folder you can use the CreateFromDirectory function as shown below.

 Collapse | Copy Code
ZipFile.CreateFromDirectory(@"D:\data",@"D:\data.zip");

If you wish to unzip, you can use the ExtractToDirectory function as shown in the below code.

 Collapse | Copy Code
ZipFile.ExtractToDirectory(@"D:\data.zip", @"D:\data\unzip");

Feature 3: Regex timeout (TimeOut)

“Regex” has been the most preferred way of doing validations. In case you are new to Regex, please see the Regex video where I have explained how regex is implemented. But because of the typical parsing logic of regex it is exposed to DOS attacks. Let us try to understand in detail what I mean by that.

For instance consider this regular expression – “^(\d+)$”. This regex expression says that it can have only numbers. You can also see the regex symbolic diagram which shows how the regex will be evaluated .Now let’s say if we want to validate “123456X”. It will have six paths as shown in the below figure.

But if we add one more number to it, it will take seven paths. In other words as the length increases a regex takes more time to evaluate. In other words the time taken to evaluate is linearly proportional to the length of the characters.

Now let’s complicate the previously defined regex from “^(\d+)$” to “^(\d+)+$” . If you see the regex symbolic diagram it’s pretty complex. If we now try to validate “123456X”, it will run through 32 paths. If you add one more character the number pf paths become 64.

In other words for the above regex, the time taken to evaluate rises exponentially with the number of characters.

Now the question you would ask is, how does it matter? This linear rise of evaluation time can be exploited by hackers to do a DOS (Denial of Service) attack. They can put a long, a really long string and make your application hang forever.

The proper solution for this would be to have a timeout on the regex operation. Good news, in .NET 4.5 you can now define a timeout property as shown in the below code. So if you get any kind of malicious string, the application will not go in a loop forever.

 Collapse | Copy Code
try
{
  var regEx = new Regex(@”^(\d+)+$”, RegexOptions.Singleline, TimeSpan.FromSeconds(2));
  var match = regEx.Match(“123453109839109283090492309480329489812093809x”);
}
catch (RegexMatchTimeoutException ex)
{
  Console.WriteLine(“Regex Timeout”);
}

Feature 4: Profile optimization (Improved startup performance)

We all know .NET code is in a half compiled format. During runtime, the JIT (Just-in-Time) compiler runs and translates this half compiled IL code to native machine code. One of the big complaints about JIT is that when a .NET applications runs the first time, it runs slow as JIT is busy translating IL code to machine code.

In order to bring down this startup time, in .NET 4.5, we have something called “profile optimization”. Profile is nothing but a simple file which has a list of methods which the application will need during startup. So when the application starts, a background JIT runs and starts translating IL code for those methods into machine / native code.

This background JIT compilation of startup methods happens across multiple processors thus minimizing the start up time further. Also note you need to have a multicore box to implement profile optimization. In case you do not have a multicore box then this setting is ignored.

In order to create the “profile” file, you first need to import the System.Runtime namespace. You can then call theSetProfileRoot and StartProfile methods of the static class ProfileOptimization. Now when the application starts the background JIT it will read from the profile file and compile your start up methods in the background thus reducing your startup time.

 Collapse | Copy Code
using System.Runtime;

// Call the Setprofilerroot and Startprofile method
ProfileOptimization.SetProfileRoot(@"D:\ProfileFile");

ProfileOptimization.StartProfile("ProfileFile");

One important note: Profileoptimization is enabled by default for ASP.NET 4.5 and Silverlight 5 applications. So the above code need not be written for these technologies.

Feature 5: Garbage collector (GC background cleanup)

Garbage collector is one real heavy task in a .NET application. And it becomes heavier when it is an ASP.NET application. ASP.NET applications run on the server and a lot of clients send requests to the server thus creating loads of objects, making the GC really work hard for cleaning up unwanted objects.

In .NET  4.0, when the GC runs for cleanup, all the application threads are suspended. You can see in the above figure we have three application threads running. We have two GCs running on separate threads. One GC thread for one logical processor. Now the application threads run and do their work. Now as these application threads are performing their task they also create managed objects.

At some point of time the background GC runs and starts clean up. When these background GCs start cleanup, they suspend all the application threads. This makes the server/application less responsive for that moment.

To overcome the above problem, server GC was introduced. In server GC there is one more thread created which runs in the background. This thread works in the background and keeps cleaning generation 2 (see this video for GC generation 0, 1, and 2)objects thus minimizing the load on the main GC thread. Due to double GC threads running, the main application threads are less suspended, thus increasing application throughput. To enable server GC, we need to use the gcServer XML tag and enable it to true.

 Collapse | Copy Code
<configuration>
   <runtime>
      <gcServer enabled="true"/>
   </runtime>
</configuration>

Three more features worth exploring

Set default culture to App Domain

In the previous versions of .NET if I needed to set culture I needed to do it in every thread. Below is a sample code which demonstrates the pain of setting culture at thread levels. That was a real pain when we had heavily multi-threaded applications.

 Collapse | Copy Code
CultureInfo cul = new CultureInfo(strCulture);
Thread.CurrentThread.CurrentCulture = cul;
Thread.CurrentThread.CurrentUICulture = cul;

In 4.5 we can set culture at the app domain level and all the threads inside that appdomain will inherit that culture. Below is a sample code of how to implement DefaultThreadCurrentCulture.

 Collapse | Copy Code
CultureInfo culture = CultureInfo.CreateSpecificCulture("fr-FR");
CultureInfo.DefaultThreadCurrentCulture = culture;

Array support more than two gigabyte size

I am not sure in what kind of a scenario we would need a 2 GB collection. So I personally do not see where we would need this feature. If I ever need such a big collection I would break it into parts. But I am sure there should be a good reason for this feature to be enabled in the framework.

Unicode support for console

I left this feature out from the discussion as very less people work with console applications. I have seen people using consoles for academic purposes. All said and done we now have Unicode support for console apps also.

References

When you have free time, do visit my site www.questpond.com for .NET 4.5 interview questions with answer videos, I have put in a lot of effort in developing this.

 

Link gốc: http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features

 

 

A Simple Scheduler in C#

Introduction

One feature many Desktop and Web Applications require is to have a Scheduler. By Scheduler one means a framework which controls the parallel execution of Jobs. These Jobs can be executed only one or repeatedly. Therefore what one wishes is to have a framework which, in order to execute a Job (once or many times), it is necessary only to implement this very Job and hook it to the framework.

The goal of this article is to show how to develop this Scheduler and explaining in details the techniques and ideas behind this implementation. One may observe that, using the right design patterns and simple solutions, the outcome can be surprisingly straightforward.

The Scheduler described here is developed in a Microsoft .NET Library Project. A Microsoft .NET Console Project uses the DLL Library in order to implement and execute a few Jobs. The next sections of this article will show how exactly this is accomplished.

Background

Schedulers have always been a concern for architects when developing Enterprise Applications. Quite often the necessity for such a framework occurs because automation of parallel tasks aids immensely the user´s work, because it takes out of his or hers hand repetitive activities.

There are many ready-to-use solutions for that. On one hand, Java, for instance, provides a few schedulers, likeQuartz. On the other hand, Microsoft .NET developers can take advantage of Windows Services.

There are situations, however, that one may not be able to use these tools. For instance, one may have to deploy an ASP.NET Application in a Shared Server and the usage of Windows Services is simply not allowed.

Even if one can use frameworks to handle scheduling events, it may be quite interesting to see how a solution can be implemented for this matter. In this case, it is a combination of using Threads adequately and implementing the Template Method Design Pattern.

Architecture

In this section the architecture is discussed. Firstly, the class diagram is displayed and explained.

The class diagram consist of the framework (in the DLL Library) along with the execution program which dispatches the Jobs. The classes Job and JobManager encomposses the the framework; It is that simple, to implement this framework. The classes RepeatableJobRepeatableJob2 and SingleExecutionJob are Job implementations. Their names give away their main characteristics.

The Job class is to be implemented in order to be executed, either as a repeatable, or a single-execution task. TheJobManager class is responsible for gathering and executing all Jobs available (classes which extend Job).

The RepeatableJob and RepeatableJob2 are never-ending Jobs, meaning their code is always executed given fixed time-defined intervals.  The SingleExecutionJob has its code run one. The only purpose of these Jobs, is to print a message stating they have been executed. This illustrates beautifully their behavior in a console, when the program is executed.

The remaining class, Program, simply instantiates the JobManager and run it. The JobManager executes the Jobs asynchronously.

After understanding the general idea of the provided classes of the application, one can now comprehend the main thoughts which are the core of this Scheduler architecture. The JobManager, gathers all Job implementation of theJob class. These Job implementations must be within the .NET Project which uses the DLL holding the Scheduler framework. After gathering these Jobs, each of them is started in a new thread. The Job class has the methodExecuteTask() which triggers the Job task implementation. If the Job is to be executed once, after the task is completed the Job finishes its execution and the thread dies. In case the Job is repeatable, the task is executed repeatedly in intervals provided by the Job´s implementation. Note here that the Job class has some methods which are implemented and others which must be provided by its implementation. This technique falls into the Method Template Design Pattern.

The next sections, the most relevant parts of the code will be explained in more details so one can have a practical understanding of how to implement the Scheduler.

Using the code

The Job class is the obvious class to start discussing. One can have a better understanding of the framework simply by looking at it.

 Collapse | Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;

namespace SchedulerManager.Mechanism
{
    /// <summary>
    /// Classes which extend this abstract class are Jobs which will be
    /// started as soon as the application starts. These Jobs are executed
    /// asynchronously from the Web Application.
    /// </summary>
    public abstract class Job
    {
        /// <summary>
        /// Execute the Job itself, one ore repeatedly, depending on
        /// the job implementation.
        /// </summary>
        public void ExecuteJob()
        {
            if (IsRepeatable())
            {
                // execute the job in intervals determined by the methd
                // GetRepetionIntervalTime()
                while (true)
                {
                    DoJob();
                    Thread.Sleep(GetRepetitionIntervalTime());
                }
            }
            // since there is no repetetion, simply execute the job
            else
            {
                DoJob();
            }
        }

        /// <summary>
        /// If this method is overriden, on can get within the job
        /// parameters set just before the job is started. In this
        /// situation the application is running and the use may have
        /// access to resources which he/she has not during the thread
        /// execution. For instance, in a web application, the user has
        /// no access to the application context, when the thread is running.
        /// Note that this method must not be overriden. It is optional.
        /// </summary>
        /// <returns>Parameters to be used in the job.</returns>
        public virtual Object GetParameters()
        {
            return null;
        }

        /// <summary>
        /// Get the Job´s Name. This name uniquely identifies the Job.
        /// </summary>
        /// <returns>Job´s name.</returns>
        public abstract String GetName();

        /// <summary>
        /// The job to be executed.
        /// </summary>
        public abstract void DoJob();

        /// <summary>
        /// Determines whether a Job is to be repeated after a
        /// certain amount of time.
        /// </summary>
        /// <returns>True in case the Job is to be repeated, false otherwise.</returns>
        public abstract bool IsRepeatable();

        /// <summary>
        /// The amount of time, in milliseconds, which the Job has to wait until it is started
        /// over. This method is only useful if IJob.IsRepeatable() is true, otherwise
        /// its implementation is ignored.
        /// </summary>
        /// <returns>Interval time between this job executions.</returns>
        public abstract int GetRepetitionIntervalTime();
    }
}

This class is well commented so its reading is quite facilitated. The idea here is to provide everything a Job needs to be executed. The methods´ explanation will be given below:

  • DoJob() – Here is to be provided the task execution itself. This means all the work to be done has to be put inside this method.
  • IsRepeatable() – Determine whether the task is to be repeated or not.
  • GetRepetitionIntervalTime() – Return the interval, in milliseconds, which the Job has to wait until it is to be executed again, in case the Job is repeatable, obviously.
  • GetName() – Uniquely identifies the Job. It is very important that this name indeed is unique among the implemented Jobs in the assembly holding them, otherwise unexpected behavior is to occur.
  • GetParameters() – This method is to be implemented when one wishes to pass parameters to the task execution. In order to access the entered parameters, only simply has to call this method within the task implementation – DoJob() method.
  • ExecuteJob() – This method executes the task itself. It calls the DoJob() method. Note that in case the method is to be run repeatedly, the DoJob() is executed in a loop, otherwise it is called only one. Here is where the Method Template Design Pattern is applied. The ExecuteJob() method is executed based on its class´s method´s implementation.

The next class to be understood is the JobManager, which is displayed below:

 Collapse | Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;
using log4net;
using SchedulerManager.Log4Net;

namespace SchedulerManager.Mechanism
{
    /// <summary>
    /// Job mechanism manager.
    /// </summary>
    public class JobManager
    {
        private ILog log = LogManager.GetLogger(Log4NetConstants.SCHEDULER_LOGGER);

        /// <summary>
        /// Execute all Jobs.
        /// </summary>
        public void ExecuteAllJobs()
        {
            log.Debug("Begin Method");

            try
            {
                // get all job implementations of this assembly.
                IEnumerable<Type> jobs = GetAllTypesImplementingInterface(typeof(Job));
                // execute each job
                if (jobs != null && jobs.Count() > 0)
                {
                    Job instanceJob = null;
                    Thread thread = null;
                    foreach (Type job in jobs)
                    {
                        // only instantiate the job its implementation is "real"
                        if (IsRealClass(job))
                        {
                            try
                            {
                                // instantiate job by reflection
                                instanceJob = (Job)Activator.CreateInstance(job);
                                log.Debug(String.Format(
                                  "The Job \"{0}\" has been instantiated successfully.", 
                                  instanceJob.GetName()));
                                // create thread for this job execution method
                                thread = new Thread(new ThreadStart(instanceJob.ExecuteJob));
                                // start thread executing the job
                                thread.Start();
                                log.Debug(String.Format(
                                  "The Job \"{0}\" has its thread started successfully.", 
                                  instanceJob.GetName()));
                            }
                            catch (Exception ex)
                            {
                                log.Error(String.Format("The Job \"{0}\" could not " + 
                                  "be instantiated or executed.", job.Name), ex);
                            }
                        }
                        else
                        {
                            log.Error(String.Format(
                              "The Job \"{0}\" cannot be instantiated.", job.FullName));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error("An error has occured while instantiating " + 
                  "or executing Jobs for the Scheduler Framework.", ex);
            }

            log.Debug("End Method");
        }

        /// <summary>
        /// Returns all types in the current AppDomain implementing the interface or inheriting the type. 
        /// </summary>
        private IEnumerable<Type> GetAllTypesImplementingInterface(Type desiredType)
        {
            return AppDomain
                .CurrentDomain
                .GetAssemblies()
                .SelectMany(assembly => assembly.GetTypes())
                .Where(type => desiredType.IsAssignableFrom(type));

        }

        /// <summary>
        /// Determine whether the object is real - non-abstract, non-generic-needed, non-interface class.
        /// </summary>
        /// <param name="testType">Type to be verified.</param>
        /// <returns>True in case the class is real, false otherwise.</returns>
        public static bool IsRealClass(Type testType)
        {
            return testType.IsAbstract == false
                && testType.IsGenericTypeDefinition == false
                && testType.IsInterface == false;
        }
    }
}

Again, this class is well commented in order to ease the understanding. Have a look at the ExecuteAllJobs()method. This method, gathers all Job implementations from the assembly its being executed and run them in separate threads. Observe that this solution is quite simple. This solution does not have the dangers of deadlocks or complicated thread interactions. Furthermore, since each thread runs independently, it is very easy to debug and find errors in this framework.

One last think to be observed are the Jobs implementations. Below are displayed the SimgleExecutionJob and the  RepeatableJob ones.

 Collapse | Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SchedulerManager.Mechanism;

namespace SchedulerConsoleApp.Jobs
{
    /// <summary>
    /// A simple job which is executed only once.
    /// </summary>
    class SimgleExecutionJob : Job
    {
        /// <summary>
        /// Get the Job Name, which reflects the class name.
        /// </summary>
        /// <returns>The class Name.</returns>
        public override string GetName()
        {
            return this.GetType().Name;
        }

        /// <summary>
        /// Execute the Job itself. Just print a message.
        /// </summary>
        public override void DoJob()
        {
            System.Console.WriteLine(String.Format("The Job \"{0}\" was executed.", 
                                       this.GetName()));
        }

        /// <summary>
        /// Determines this job is not repeatable.
        /// </summary>
        /// <returns>Returns false because this job is not repeatable.</returns>
        public override bool IsRepeatable()
        {
            return false;
        }

        /// <summary>
        /// In case this method is executed NotImplementedException is thrown
        /// because this method is not to to be used. This method is never used
        /// because it serves the purpose of stating the interval of which the job
        /// will be executed repeatedly. Since this job is a single-execution one,
        /// this method is rendered useless.
        /// </summary>
        /// <returns>Returns nothing because this method is not to be used.</returns>
        public override int GetRepetitionIntervalTime()
        {
            throw new NotImplementedException();
        }
    }
}
 Collapse | Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SchedulerManager.Mechanism;

namespace SchedulerConsoleApp.Jobs
{
    /// <summary>
    /// A simple repeatable Job.
    /// </summary>
    class RepeatableJob : Job
    {
        /// <summary>
        /// Counter used to count the number of times this job has been
        /// executed.
        /// </summary>
        private int counter = 0;

        /// <summary>
        /// Get the Job Name, which reflects the class name.
        /// </summary>
        /// <returns>The class Name.</returns>
        public override string GetName()
        {
            return this.GetType().Name;
        }

        /// <summary>
        /// Execute the Job itself. Just print a message.
        /// </summary>
        public override void DoJob()
        {
            System.Console.WriteLine(String.Format(
              "This is the execution number \"{0}\" of the Job \"{1}\".", 
              counter.ToString(), this.GetName()));
            counter++;
        }

        /// <summary>
        /// Determines this job is repeatable.
        /// </summary>
        /// <returns>Returns true because this job is repeatable.</returns>
        public override bool IsRepeatable()
        {
            return true;
        }

        /// <summary>
        /// Determines that this job is to be executed again after
        /// 1 sec.
        /// </summary>
        /// <returns>1 sec, which is the interval this job is to be
        /// executed repeatadly.</returns>
        public override int GetRepetitionIntervalTime()
        {
            return 1000;
        }
    }
}

Note how straightforward they are: the SimgleExecutionJob provides its identifier based on its class name, implements the task, which is to print a message, and tells the Job is not repeatable. The RepeatableJob, does state the task is repetitive, provides the interval of execution, gives the class name to use as its identifier, and defines its task as a simple message printing.

Compiling and Running the Code

When one opens the code and tries to compile it, errors are displayed stating that there is no log4net libraries. This occurs because it is not allowed to upload .dll files in CodeProject articles, thus the log4net.dll was removed. Therefore, to fix the Solution Setup and build it correctly, download the log4net library clicking here.  After that, create a sub-directory called libraries in the folder SchedulerManager-noexe. Inside the directory libraries copy thelog4net.dll file one has just downloaded. Finally, refresh the SchedulerManager project references and you should see that the log4net reference has no warning flag. Compile the solution and run the SchedulerConsoleApp project.

Discussion

Firstly, note the simplicity of this solution, as stated before. Simply put, one gathers all Job implementations and executes them in separate threads. This straightforwardness allows one to easily add more functionalities to this framework.

In the subject of new features, one may consider having the Job´s requirements in a database. For instance, whether or not the job is repeatable, interval of execution, could be all stored in a database, each row identified by its unique name. This makes maintenance easier because in order to change their parameters execution no code change is necessary, simply database changes are needed.

Other features, such as, interface to handle the Job Management, the ability to run, pause and cancel a Job execution could also be implemented. Note however, that while these features seem nice and fancy, in most of applications there are rarely needed.

Many people argue that dealing with threads in Web Applications can be very dangerous because it may jeopardize the Application Sever. In this author´s experience, it could not be further from the truth, at least when one is working with Internet Information Services.

 

Link gốc: http://www.codeproject.com/Articles/591271/A-Simple-Scheduler-in-Csharp

The Template Method Design Pattern using C# .Net

First of all I’ll just put this pattern in context and describe its intent as in the GOF book:

Template Method:

Define the skeleton of an algorithm in an operation, deferring some steps to

Subclasses. Template Method lets subclasses redefine certain steps of an algorithm

without changing the Algorithm’s Structure. 

 

Usage:

When you are certain about the High Level steps involved in an Algorithm/Work flow you can use the Template Pattern which allows the Base Class to define the Sequence of the Steps but permits the Sub classes to alter the implementation of any/all steps.

Example in the .Net framework:

The most common example is the Asp.Net Page Life Cycle. The Page Life Cycle has a few methods which are called in a sequence but we have the liberty to modify the functionality of any of the methods by overriding them.

Sample implementation of Template Method Pattern:

Let’s see the class diagram first:

And here goes the code:

EmailBase.cs

    1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Threading.Tasks;

6

7 namespace TemplateMethod

8 {

9     public abstract class EmailBase

10     {

11

12         public bool SendEmail()

13         {

14             if (CheckEmailAddress() == true) // Method1 in the sequence

15             {

16                 if (ValidateMessage() == true) // Method2 in the sequence

17                 {

18                     if (SendMail() == true) // Method3 in the sequence

19                     {

20                         return true;

21                     }

22                     else

23                     {

24                         return false;

25                     }

26

27                 }

28                 else

29                 {

30                     return false;

31                 }

32

33             }

34             else

35             {

36                 return false;

37

38             }

39

40

41         }

42

43         protected abstract bool CheckEmailAddress();

44         protected abstract bool ValidateMessage();

45         protected abstract bool SendMail();

46

47

48     }

49 }

50

EmailYahoo.cs

    1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Threading.Tasks;

6

7 namespace TemplateMethod

8 {

9     public class EmailYahoo:EmailBase

10     {

11

12         protected override bool CheckEmailAddress()

13         {

14             Console.WriteLine(“Checking Email Address : YahooEmail”);

15             return true;

16         }

17         protected override bool ValidateMessage()

18         {

19             Console.WriteLine(“Validating Email Message : YahooEmail”);

20             return true;

21         }

22

23

24         protected override bool SendMail()

25         {

26             Console.WriteLine(“Semding Email : YahooEmail”);

27             return true;

28         }

29

30

31     }

32 }

33

 EmailGoogle.cs

    1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Threading.Tasks;

6

7 namespace TemplateMethod

8 {

9     public class EmailGoogle:EmailBase

10     {

11

12         protected override bool CheckEmailAddress()

13         {

14             Console.WriteLine(“Checking Email Address : GoogleEmail”);

15             return true;

16         }

17         protected override bool ValidateMessage()

18         {

19             Console.WriteLine(“Validating Email Message : GoogleEmail”);

20             return true;

21         }

22

23

24         protected override bool SendMail()

25         {

26             Console.WriteLine(“Semding Email : GoogleEmail”);

27             return true;

28         }

29

30

31     }

32 }

33

Program.cs

    1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Threading.Tasks;

6

7 namespace TemplateMethod

8 {

9     class Program

10     {

11         static void Main(string[] args)

12         {

13             Console.WriteLine(“Please choose an Email Account to send an Email:”);

14             Console.WriteLine(“Choose 1 for Google”);

15             Console.WriteLine(“Choose 2 for Yahoo”);

16             string choice = Console.ReadLine();

17             EmailBase email;

17

18             if (choice == “1”)

19             {

20                 email = new EmailGoogle(); // Rather than newing it up here, you may use a factory to do so.

21                 email.SendEmail();

22

23             }

24             if (choice == “2”)

25             {

26                 email = new EmailYahoo(); // Rather than newing it up here, you may use a factory to do so.

27                 email.SendEmail();

28             }

29         }

30     }

31 }

32

Final Words:

It’s very obvious that why the Template Method Pattern is a popular pattern, everything at last revolves around Algorithms and if you are clear with the steps involved it makes real sense to delegate the duty of implementing the step’s functionality to the sub classes.

Link gốc: http://weblogs.asp.net/saurabhnijhawan/archive/2012/10/15/the-template-method-design-pattern-using-c-net.aspx

Template Method in C#

definition

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.Frequency of use:   medium

UML class diagram

participants

The classes and/or objects participating in this pattern are:

  • AbstractClass  (DataObject)
    • defines abstract primitive operations that concrete subclasses define to implement steps of an algorithm
    • implements a template method defining the skeleton of an algorithm. The template method calls primitive operations as well as operations defined in AbstractClass or those of other objects.
  • ConcreteClass  (CustomerDataObject)
    • implements the primitive operations ot carry out subclass-specific steps of the algorithm

sample code in C#

This structural code demonstrates the Template method which provides a skeleton calling sequence of methods. One or more steps can be deferred to subclasses which implement these steps without changing the overall calling sequence.

Show code

// Template Method pattern — Structural example

This real-world code demonstrates a Template method named Run() which provides a skeleton calling sequence of methods. Implementation of these steps are deferred to the CustomerDataObject subclass which implements the Connect, Select, Process, and Disconnect methods.

Hide code

// Template Method pattern — Real World example

using System;

using System.Data;

using System.Data.OleDb;

namespace DoFactory.GangOfFour.Template.RealWorld

{

/// <summary>

/// MainApp startup class for Real-World

/// Template Design Pattern.

/// </summary>

class MainApp

{

/// <summary>

/// Entry point into console application.

/// </summary>

static void Main()

{

DataAccessObject daoCategories = new Categories();

daoCategories.Run();

DataAccessObject daoProducts = new Products();

daoProducts.Run();

// Wait for user

Console.ReadKey();

}

}

/// <summary>

/// The ‘AbstractClass’ abstract class

/// </summary>

abstract class DataAccessObject

{

protected string connectionString;

protected DataSet dataSet;

public virtual void Connect()

{

// Make sure mdb is available to app

connectionString =

“provider=Microsoft.JET.OLEDB.4.0; ” +

“data source=..\\..\\..\\db1.mdb”;

}

public abstract void Select();

public abstract void Process();

public virtual void Disconnect()

{

connectionString = “”;

}

// The ‘Template Method’

public void Run()

{

Connect();

Select();

Process();

Disconnect();

}

}

/// <summary>

/// A ‘ConcreteClass’ class

/// </summary>

class Categories : DataAccessObject

{

public override void Select()

{

string sql = “select CategoryName from Categories”;

OleDbDataAdapter dataAdapter = new OleDbDataAdapter(

sql, connectionString);

dataSet = new DataSet();

dataAdapter.Fill(dataSet, “Categories”);

}

public override void Process()

{

Console.WriteLine(“Categories —- “);

DataTable dataTable = dataSet.Tables[“Categories”];

foreach (DataRow row in dataTable.Rows)

{

Console.WriteLine(row[“CategoryName”]);

}

Console.WriteLine();

}

}

/// <summary>

/// A ‘ConcreteClass’ class

/// </summary>

class Products : DataAccessObject

{

public override void Select()

{

string sql = “select ProductName from Products”;

OleDbDataAdapter dataAdapter = new OleDbDataAdapter(

sql, connectionString);

dataSet = new DataSet();

dataAdapter.Fill(dataSet, “Products”);

}

public override void Process()

{

Console.WriteLine(“Products —- “);

DataTable dataTable = dataSet.Tables[“Products”];

foreach (DataRow row in dataTable.Rows)

{

Console.WriteLine(row[“ProductName”]);

}

Console.WriteLine();

}

}

}

Output

Categories —-
Beverages
Condiments
Confections
Dairy Products
Grains/Cereals
Meat/Poultry
Produce
SeafoodProducts —-
Chai
Chang
Aniseed Syrup
Chef Anton’s Cajun Seasoning
Chef Anton’s Gumbo Mix
Grandma’s Boysenberry Spread
Uncle Bob’s Organic Dried Pears
Northwoods Cranberry Sauce
Mishi Kobe Niku

 

Link gốc: http://dofactory.com/Patterns/PatternTemplate.aspx#_self1