Tuesday, December 11, 2012

-- TSQL Search for specified word in Stored Procedures


-- TSQL Search for specified word in Stored Procedures

 SELECT obj.Name SPName, sc.TEXT SPText
FROM sys.syscomments sc
INNER JOIN sys.objects obj ON sc.Id = obj.OBJECT_ID
WHERE sc.TEXT LIKE '%' + 'TextToSearch' + '%'
AND TYPE = 'P'


--tsql find column around database tables

SELECT t.name AS table_name,
SCHEMA_NAME(schema_id) AS schema_name,
c.name AS column_name
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE c.name LIKE '%DelFlag%'
ORDER BY schema_name, table_name;


Monday, December 10, 2012

Using sp_executesql

MSDN :


To execute a string, we recommend that you use the sp_executesql stored procedure instead of the EXECUTE statement. Because this stored procedure supports parameter substitution, sp_executesql is more versatile than EXECUTE; and because sp_executesql generates execution plans that are more likely to be reused by SQL Server, sp_executesql is more efficient than EXECUTE.
When either sp_executesql or the EXECUTE statement executes a string, the string is executed as its own self-contained batch. SQL Server compiles the Transact-SQL statement or statements in the string into an execution plan that is separate from the execution plan of the batch that contained the sp_executesql or the EXECUTE statement. The following rules apply for self-contained batches:
  • The Transact-SQL statements in the sp_executesql or EXECUTE string are not compiled into an execution plan until sp_executesql or the EXECUTE statement are executed. The strings are not parsed or checked for errors until they are executed. The names referenced in the strings are not resolved until they are executed.
  • The Transact-SQL statements in the executed string do not have access to any variables declared in the batch that contains sp_executesql or the EXECUTE statement. The batch that contains sp_executesql or the EXECUTE statement does not have access to variables or local cursors defined in the executed string.
  • If the executed string contains a USE statement that changes the database context, the change to the database context only lasts until sp_executesql or the EXECUTE statement has finished running.
Running the following two batches illustrates these points:
/*Show not having access to variables from the calling batch. */
DECLARE @CharVariable CHAR(3);
SET @CharVariable = 'abc';
/* sp_executesql fails because @CharVariable has gone out of scope. */
EXECUTE sp_executesql N'PRINT @CharVariable';
GO

/* Show database context resetting after sp_executesql finishes. */
USE master;
GO
EXECUTE sp_executesql N'USE AdventureWorks2008R2;'
GO
/* This statement fails because the database context
   has now returned to master. */
SELECT * FROM Sales.Store;
GO
sp_executesql supports the substitution of parameter values for any parameters that are specified in the Transact-SQL string, but the EXECUTE statement does not. Therefore, the Transact-SQL strings that are generated by sp_executesql are more similar than those generated by the EXECUTE statement. The SQL Server query optimizer will probably match the Transact-SQL statements from sp_executesql with execution plans from the previously executed statements, saving the overhead of compiling a new execution plan.
With the EXECUTE statement, all parameter values must be converted to character or Unicode and made a part of the Transact-SQL string.
If the statement is executed repeatedly, a completely new Transact-SQL string must be built for each execution, even when the only differences are in the values supplied for the parameters. This generates additional overhead in the following ways:
  • The ability of the SQL Server query optimizer to match the new Transact-SQL string with an existing execution plan is hampered by the constantly changing parameter values in the text of the string, especially in complex Transact-SQL statements.
  • The whole string must be rebuilt for each execution.
  • Parameter values (other than character or Unicode values) must be cast to a character or Unicode format for each execution.
sp_executesql supports setting of parameter values separately from the Transact-SQL string:
DECLARE @IntVariable INT;
DECLARE @SQLString NVARCHAR(500);
DECLARE @ParmDefinition NVARCHAR(500);

/* Build the SQL string one time. */
SET @SQLString =
     N'SELECT * FROM AdventureWorks2008R2.Sales.Store WHERE SalesPersonID = @SalesID';
/* Specify the parameter format one time. */
SET @ParmDefinition = N'@SalesID int';

/* Execute the string with the first parameter value. */
SET @IntVariable = 275;
EXECUTE sp_executesql @SQLString, @ParmDefinition,
                      @SalesID = @IntVariable;
/* Execute the same string with the second parameter value. */
SET @IntVariable = 276;
EXECUTE sp_executesql @SQLString, @ParmDefinition,
                      @SalesID = @IntVariable;
sp_executesql offers the following additional benefits:
  • Because the actual text of the Transact-SQL statement does not change between executions, the query optimizer should match the Transact-SQL statement in the second execution with the execution plan generated for the first execution. Therefore, SQL Server does not have to compile the second statement.
  • The Transact-SQL string is built only one time.
  • The integer parameter is specified in its native format. Conversion to Unicode is not required.
    NoteNote
    Object names in the statement string must be fully qualified for SQL Server to reuse the execution plan.
In earlier versions of SQL Server, the only way to be able to reuse execution plans is to define the Transact-SQL statements as a stored procedure and have the application execute the stored procedure. This generates additional administrative overhead for the applications. Using sp_executesql can help reduce this overhead and still let SQL Server reuse execution plans. sp_executesql can be used instead of stored procedures when executing a Transact-SQL statement several times, when the only variation is in the parameter values supplied to the Transact-SQL statement. Because the Transact-SQL statements themselves remain constant and only the parameter values change, the SQL Server query optimizer is likely to reuse the execution plan it generates for the first execution.
The following example builds and executes a DBCC CHECKDB statement for every database on a server, except for the four system databases.
USE master;
GO
SET NOCOUNT ON;
GO
DECLARE AllDatabases CURSOR FOR
SELECT name FROM sys.databases WHERE database_id > 4
OPEN AllDatabases;

DECLARE @DBNameVar NVARCHAR(128);
DECLARE @Statement NVARCHAR(300);

FETCH NEXT FROM AllDatabases INTO @DBNameVar;
WHILE (@@FETCH_STATUS = 0)
BEGIN
   PRINT N'CHECKING DATABASE ' + @DBNameVar;
   SET @Statement = N'USE ' + @DBNameVar + CHAR(13)
      + N'DBCC CHECKDB (' + @DBNameVar + N')' + N'WITH PHYSICAL_ONLY';
   EXEC sp_executesql @Statement;
   PRINT CHAR(13) + CHAR(13);
   FETCH NEXT FROM AllDatabases INTO @DBNameVar;
END;

CLOSE AllDatabases;
DEALLOCATE AllDatabases;
GO
SET NOCOUNT OFF;
GO
The SQL Server ODBC driver uses sp_executesql to implement SQLExecDirect when the Transact-SQL statement that is being executed contains bound parameter markers. This extends the advantages provided bysp_executesql to all applications that use ODBC or APIs defined over ODBC, such as RDO. Existing ODBC applications ported to SQL Server automatically acquire the performance gains without having to be rewritten. The one exception is that sp_executesql is not used with data-at-execution parameters. For more information, see Using Statement Parameters.
The SQL Server Native Client ODBC Provider also uses sp_executesql to implement the direct execution of statements with bound parameters. Applications that use OLE DB or ADO gain the advantages provided bysp_executesql without having to be rewritten.


TSql Manipulating XML (XQUERY)


--TSQL SELECT FROM XML FIELD

DECLARE @xmlData XML
set @xmlData='<?xml version="1.0"?>
<ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ITEM>
<FilterID>1219</FilterID>
<Name>Fred</Name>
<Code>510</Code>
<Department>N</Department>
<Number>305327</Number>
</ITEM>
<ITEM>
<FilterID>3578</FilterID>
<Name>Gary</Name>
<Code>001</Code>
<Department>B</Department>
<Number>0692690</Number>
</ITEM>
<ITEM>
<FilterID>3579</FilterID>
<Name>George</Name>
<Code>001</Code>
<Department>X</Department>
<Number>35933</Number>
</ITEM>
</ROOT>'


SELECT
  ref.value('FilterID[1]', 'int') AS FilterID ,
  ref.value('Name[1]', 'NVARCHAR (10)') AS Name ,
  ref.value('Code[1]', 'NVARCHAR (10)') AS Code ,
  ref.value('Department[1]', 'NVARCHAR (3)') AS Department,
  ref.value('Number[1]', 'int') AS Number    
FROM @xmlData.nodes('/ROOT/ITEM')
xmlData( ref )

--TSQL SELECT TO XML FIELD

select * from dbo.TBLFOO
        FOR XML PATH('ITEM'), root('ROOT')

Wednesday, December 5, 2012

SQL SERVER GET FOREIGN CONSTRAINTS RELATTIONS


--HOW TO GET FOREIGN CONSTRAINTS RELATED TO THIS TABLE

 SELECT
        FK_Table  = FK.TABLE_NAME,
        FK_Column = CU.COLUMN_NAME,
        PK_Table  = PK.TABLE_NAME,
        PK_Column = PT.COLUMN_NAME,
        Constraint_Name = C.CONSTRAINT_NAME
    FROM
        INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
        INNER JOIN
        INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK
            ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
        INNER JOIN
        INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK
            ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
        INNER JOIN
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
            ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
        INNER JOIN
        (
            SELECT
                i1.TABLE_NAME, i2.COLUMN_NAME
            FROM
                INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
                INNER JOIN
                INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2
                ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
                WHERE i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
        ) PT
        ON PT.TABLE_NAME = PK.TABLE_NAME

    WHERE PK.TABLE_NAME='TABLE_NAME'

--HOW TO GET FOREIGN CONSTRAINTS USED IN THIS TABLE


SELECT
    c.name
    , target.name
    , targetc.name
FROM
    -- source table
    sysobjects t
    -- source column
    INNER JOIN syscolumns c ON t.id = c.id
    -- general constraint
    INNER JOIN sysconstraints co ON t.id = co.id AND co.colid = c.colid
    -- foreign key constraint
    INNER JOIN sysforeignkeys fk ON co.constid = fk.constid
    -- target table
    INNER JOIN sysobjects target ON fk.rkeyid = target.id
    -- target column
    INNER JOIN syscolumns targetc ON fk.rkey = targetc.colid AND fk.rkeyid = targetc.id
WHERE
    t.name = 'TABLE_NAME'

--OR

exec sp_fkeys @fktable_name = 'TABLE_NAME'



Tuesday, December 4, 2012

c# difference var and dynamic keyword


var is static typed - the compiler and runtime know the type - they just save you some typing... the following are 100% identical:
var s = "abc";
Console.WriteLine(s.Length);
and
string s = "abc";
Console.WriteLine(s.Length);
All that happened was that the compiler figured out that s must be a string (from the initializer). In both cases, it knows (in the IL) that s.Length means the (instance) string.Length property.
dynamic is a very different beast; it is most similar to object, but with dynamic dispatch:
dynamic s = "abc";
Console.WriteLine(s.Length);
Here, s is typed as dynamic. It doesn't know about string.Length, because it doesn't know anything about s at compile time. For example, the following would compile (but not run) too:
dynamic s = "abc";
Console.WriteLine(s.FlibbleBananaSnowball);
At runtime (only), it would check for the FlibbleBananaSnowball property - fail to find it, and explode in a shower of sparks.
With dynamic, properties / methods / operators / etc are resolved at runtime, based on the actual object. Very handy for talking to COM (which can have runtime-only properties), the DLR, or other dynamic systems, like javascript.
.

Variables declared with var are implicitly but statically typed. Variables declared with dynamic are dynamically typed. This capability was added to the CLR in order to support dynamic languages like Ruby and Python.
I should add that this means that dynamic declarations are resolved at run-time, var declarations are resolved at compile-time.
.
http://stackoverflow.com/questions/961581/whats-the-difference-between-dynamicc-4-and-var

Monday, November 19, 2012

Working with the ASP.NET Global.asax file


Working with the ASP.NET Global.asax file
The Global.asax file, sometimes called the ASP.NET application file, provides a way to respond to application or module level events in one central location. You can use this file to implement application security, as well as other tasks. Let's take a closer look at how you may use it in your application development efforts.
Overview
The Global.asax file is in the root application directory. While Visual Studio .NET automatically inserts it in all new ASP.NET projects, it's actually an optional file. It's okay to delete it—if you aren't using it. The .asax file extension signals that it's an application file rather than an ASP.NET file that uses aspx.
The Global.asax file is configured so that any direct HTTP request (via URL) is rejected automatically, so users cannot download or view its contents. The ASP.NET page framework recognizes automatically any changes that are made to the Global.asax file. The framework reboots the application, which includes closing all browser sessions, flushes all state information, and restarts the application domain.
Programming
The Global.asax file, which is derived from the HttpApplication class, maintains a pool of HttpApplication objects, and assigns them to applications as needed. The Global.asax file contains the following events:
·         Application_Init: Fired when an application initializes or is first called. It's invoked for all HttpApplication object instances.
·         Application_Disposed: Fired just before an application is destroyed. This is the ideal location for cleaning up previously used resources.
·         Application_Error: Fired when an unhandled exception is encountered within the application.
·         Application_Start: Fired when the first instance of the HttpApplication class is created. It allows you to create objects that are accessible by all HttpApplication instances.
·         Application_End: Fired when the last instance of an HttpApplication class is destroyed. It's fired only once during an application's lifetime.
·         Application_BeginRequest: Fired when an application request is received. It's the first event fired for a request, which is often a page request (URL) that a user enters.
·         Application_EndRequest: The last event fired for an application request.
·         Application_PreRequestHandlerExecute: Fired before the ASP.NET page framework begins executing an event handler like a page or Web service.
·         Application_PostRequestHandlerExecute: Fired when the ASP.NET page framework is finished executing an event handler.
·         Applcation_PreSendRequestHeaders: Fired before the ASP.NET page framework sends HTTP headers to a requesting client (browser).
·         Application_PreSendContent: Fired before the ASP.NET page framework sends content to a requesting client (browser).
·         Application_AcquireRequestState: Fired when the ASP.NET page framework gets the current state (Session state) related to the current request.
·         Application_ReleaseRequestState: Fired when the ASP.NET page framework completes execution of all event handlers. This results in all state modules to save their current state data.
·         Application_ResolveRequestCache: Fired when the ASP.NET page framework completes an authorization request. It allows caching modules to serve the request from the cache, thus bypassing handler execution.
·         Application_UpdateRequestCache: Fired when the ASP.NET page framework completes handler execution to allow caching modules to store responses to be used to handle subsequent requests.
·         Application_AuthenticateRequest: Fired when the security module has established the current user's identity as valid. At this point, the user's credentials have been validated.
·         Application_AuthorizeRequest: Fired when the security module has verified that a user can access resources.
·         Session_Start: Fired when a new user visits the application Web site.
·         Session_End: Fired when a user's session times out, ends, or they leave the application Web site.
The event list may seem daunting, but it can be useful in various circumstances.
A key issue with taking advantage of the events is knowing the order in which they're triggered. The Application_Init and Application_Start events are fired once when the application is first started. Likewise, the Application_Disposed and Application_End are only fired once when the application terminates. In addition, the session-based events (Session_Start and Session_End) are only used when users enter and leave the site. The remaining events deal with application requests, and they're triggered in the following order:
·         Application_BeginRequest
·         Application_AuthenticateRequest
·         Application_AuthorizeRequest
·         Application_ResolveRequestCache
·         Application_AcquireRequestState
·         Application_PreRequestHandlerExecute
·         Application_PreSendRequestHeaders
·         Application_PreSendRequestContent
·         <<code is executed>>
·         Application_PostRequestHandlerExecute
·         Application_ReleaseRequestState
·         Application_UpdateRequestCache
·         Application_EndRequest
A common use of some of these events is security. The following C# example demonstrates various Global.asax events with the Application_Authenticate event used to facilitate forms-based authentication via a cookie. In addition, the Application_Start event populates an application variable, while Session_Start populates a session variable. The Application_Error event displays a simple message stating an error has occurred.
protected void Application_Start(Object sender, EventArgs e) {
Application["Title"] = "Builder.com Sample";
}
protected void Session_Start(Object sender, EventArgs e) {
Session["startValue"] = 0;
}
protected void Application_AuthenticateRequest(Object sender, EventArgs e) {
// Extract the forms authentication cookie
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if(null == authCookie) {
// There is no authentication cookie.
return;
}
FormsAuthenticationTicket authTicket = null;
try {
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
} catch(Exception ex) {
// Log exception details (omitted for simplicity)
return;
}
if (null == authTicket) {
// Cookie failed to decrypt.
return;
}
// When the ticket was created, the UserData property was assigned
// a pipe delimited string of role names.
string[2] roles
roles[0] = "One"
roles[1] = "Two"
// Create an Identity object
FormsIdentity id = new FormsIdentity( authTicket );
// This principal will flow throughout the request.
GenericPrincipal principal = new GenericPrincipal(id, roles);
// Attach the new principal object to the current HttpContext object
Context.User = principal;
}
protected void Application_Error(Object sender, EventArgs e) {
Response.Write("Error encountered.");
}
This example provides a peek at the usefulness of the events contained in the Global.asax file; it's important to realize that these events are related to the entire application. Consequently, any methods placed in it are available through the application's code, hence the Global name.
Here's the VB.NET equivalent of the previous code:
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Application("Title") = "Builder.com Sample"
End Sub
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
Session("startValue") = 0
End Sub
Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As
 EventArgs)
' Extract the forms authentication cookie
Dim cookieName As String
cookieName = FormsAuthentication.FormsCookieName
Dim authCookie As HttpCookie
authCookie = Context.Request.Cookies(cookieName)
If (authCookie Is Nothing) Then
' There is no authentication cookie.
Return
End If
Dim authTicket As FormsAuthenticationTicket
authTicket = Nothing
Try
authTicket = FormsAuthentication.Decrypt(authCookie.Value)
Catch ex As Exception
' Log exception details (omitted for simplicity)
Return
End Try
Dim roles(2) As String
roles(0) = "One"
roles(1) = "Two"
Dim id As FormsIdentity
id = New FormsIdentity(authTicket)
Dim principal As GenericPrincipal
principal = New GenericPrincipal(id, roles)
' Attach the new principal object to the current HttpContext object
Context.User = principal
End Sub
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Response.Write("Error encountered.")
End Sub
A good resource
The Global.asax file is the central point for ASP.NET applications. It provides numerous events to handle various application-wide tasks such as user authentication, application start up, and dealing with user sessions. You should be familiar with this optional file to build robust ASP.NET-based applications.

http://www.techrepublic.com/article/working-with-the-aspnet-globalasax-file/5771721


Monday, November 5, 2012

How to solve IIS 7 , 7.5 [ Handler "PageHandlerFactory-Integrated" has a bad module "ManagedPipelineHandler" in its module list ] Problem

Run "aspnet_regiis.exe" program from command line (within Command Prompt):
%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe /i

in win 64 Run "aspnet_regiis.exe" program from command line (within Command Prompt):

%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe /i

Wednesday, October 31, 2012

Creating a Plug-In Framework


Creating a Plug-In Framework

Why Do You Need a Plug-In Framework for Your Application?

People usually add plug-in support in their applications for the following reasons:
  • To extend an application's functionality without the need to re-compile and distribute it to customers.
  • To add functionality without requiring access to the original source code.
  • The business rules for the application change frequently, or new rules are added frequently.
In this article, youll build a very simple text editor, composed of only one form. All it will be able to do is to display text in a single textbox in the middle of the form. Once this application is ready, you'll create a simple plug-in and add it to the application. That plug-in will be able to read the text currently in the textbox, parse it for valid e-mail addresses, and return a string containing only those e-mails. You will then put this text inside the text box.
As you can see, there are a number of "unknowns" in this case study:
  • How do you find the plug-in from within the application?
  • How does the plug-in know what text is in the text box?
  • How do you activate this plug-in?
The answers to all of these questions will become clear as we build the solution.

Step 1. Create a Simple Text Editor

I won't bore you with the details of this. It's all in the source code download: just a simple form showing a lump of text. I'll assume from this moment that you have created this simple application.

Step 2. Create the Plug-In SDK

Now that you have an application, you will want it to be able to talk with external plug-ins. How do you make this happen?
The solution is for the application to work against a published interface, a set of public members and methods that will be implemented by all custom plug-ins. I'll call this interface IPlugin. From now on, any developer that would like to create a plug-in for your application will have to implement this interface. This interface will be located at a shared library, which both your application and any custom plug-ins will reference.
To define this interface, you need just a little data from your simple plug-in—its name, and a method that would instruct it to perform a generic action based upon the data in your application.
public interface IPlugin
{
   string Name{get;}
   void PerformAction(IPluginContext context);
}

The code is straightforward, but why send an IPluginContext interface to thePerformAction? The reason you send an interface rather than just a string is to allow more flexibility as to what object you will be able to send. Currently, this interface is very simple:
public interface IPluginContext
{
   string CurrentDocumentText{get;set;}
}

Now, all you have to do is implement this interface in one or more objects, and send this to any plug-in to receive a result. In the future this will allow you to change the string of not just a textbox, but any object you like.

Step 3. Creating Your Custom Plug-In

All you have to do now is:
  • Create a separate class library object.
  • Create a class that implements the IPlugin Interface.
  • Compile that class and place it in the same folder as the main application.
public class EmailPlugin:IPlugin
{
   public EmailPlugin()
   {
   }
   // The single point of entry to our plugin
   // Acepts an IPluginContext object
// which holds the current
   // context of the running editor.
   // It then parses the text found inside the editor
   // and changes it to reflect any
// email addresses that are found.
   public void PerformAction(IPluginContext context)
   {
      context.CurrentDocumentText=
             ParseEmails(context.CurrentDocumentText);
   }

   // The name of the plugin as it will appear
   // under the editor's "Plugins" menu
   public string Name
   {
      get
      {
         return "Email Parsing Plugin";
      }
   }

   // Parse the given string for any emails using the Regex Class
   // and return a string containing only email addresses
   private string ParseEmails(string text)
   {
      const string emailPattern= @"\w+@\w+\.\w+((\.\w+)*)?";
      MatchCollection emails =
               Regex.Matches(text,emailPattern,
               RegexOptions.IgnoreCase);
      StringBuilder emailString = new StringBuilder();
      foreach(Match email in emails)
      {
         emailString.Append(email.Value + Environment.NewLine);
      }

      return emailString.ToString();
   }
}

Step 4. Letting Your Application Know About the New Plug-In

Once you have compiled your plug-in, how do you let your application know about it?
The solution is simple:
  • Create an application configuration file.
  • Create a section in the config file that lists all the available plug-ins.
  • Create a parser for this config section.
To complete step one, just add an XML file to the main application.
Tip   Name this file App.Config. This way, every time you build your application, Microsoft® Visual Studio .NET will automatically copy this file into the build output folder and rename it to <yourApp>.Config ,saving you the hassle.
Now, the plug-in developer should be able to easily add an entry in the config file to publish each plug-in he creates. Here's how the config file should look:
<configuration>
<configSections>
      <section name="plugins"
            type="Royo.PluggableApp.PluginSectionHandler, PluggableApp"
            />
</configSections>
   <plugins>
      <plugin type="Royo.Plugins.Custom.EmailPlugin, CustomPlugin" />
   </plugins>
</configuration>

Notice the configSections Tag. This tells the application configuration settings that you have a plug-ins section in this config file, and that you have a parser for this section. This parser resides in the classRoyo.PluggableApp.PluginSectionHandler, which is in an assembly namedPluggableApp. I'll show you the code for this class below.
Next, you have the plug-ins section of the config file, which lists, for every plug-in, the class name and the assembly name in which it resides. You will use this information when you instantiate the plug-in, later on.
Once the config file is done, you have finished one end of the circle. The plug-in is ready to rock, and has published itself to all the necessary channels. All you have to do now is to enable your application to read in this information, and instantiate the published plug-ins according to this information.

Step 5. Parse the Config File Using IConfigurationSectionHandler


In order to parse out the plug-ins found within the config file of the application, the framework provides a very simple mechanism enabling you to register a specific class as a handler for a specific portion in your config file. You must have a handler for any portion in the file that is not automatically parsed by the framework; otherwise you will get a ConfigurationException thrown.
In order to provide the class that parses the plug-ins section, all you need to do is to implement the System.Configuration.IConfigurationSectionHandlerinterface. The interface itself is very simple:
public interface IConfigurationSectionHandler
{
   public object Create(object parent, object configContext, System.Xml.XmlNode section);
}

All you have to do is override the Create method in your custom class, and parse the XML node that is provided to you. This XML node, in this case, will be the "Plugins" XML node. Once you have that, you have all the information needed to instantiate the plug-ins for your application.
Your custom class must provide a default constructor, since it is instantiated automatically by the framework at run time, and then the Create method is called on it. Here's the code for the PluginSectionHandler class:
public class PluginSectionHandler:IConfigurationSectionHandler
{
   public PluginSectionHandler()
   {
   }
   // Iterate through all the child nodes
   //   of the XMLNode that was passed in and create instances
   //   of the specified Types by reading the attribite values of the nodes
   //   we use a try/Catch here because some of the nodes
   //   might contain an invalid reference to a plugin type
   public object Create(object parent,
         object configContext,
         System.Xml.XmlNode section)
   {
      PluginCollection plugins = new PluginCollection();
      foreach(XmlNode node in section.ChildNodes)
      {
         //Code goes here to instantiate
         //and invoke the plugins
         .
         .
         .
      }
      return plugins;
   }
}

As you can see in the config file mentioned earlier, you provide the data the framework needs in order to handle the plug-ins section using the configSection tag prior to the actual plug-ins tags.
<configuration>
<configSections>
   <section name="plugins"
      type="Royo.PluggableApp.PluginSectionHandler, PluggableApp"
   />
</configSections>
.
.
.
Notice how to specify the class. The string is composed of two sections: the full name of the class (including encapsulating namespaces), comma, the name of the assembly in which this class is located. This is all the framework needs to instantiate a class, and unsurprisingly, this is exactly the information required for any plug-ins to register for your application.

Instantiating and Invoking the Plug-Ins

Okay, so how would you actually instantiate an instance of a plug-in given the following string?
String ClassName = "Royo.Plugins.MyCustomPlugin, MyCustomPlugin"
IPlugin plugin =  (IPlugin )Activator.CreateInstance(Type.GetType(ClassName));

What's happening here is this: Since your application does not make a direct reference to the assembly of the custom plug-in, you use theSystem.Activator class. Activator is a special class able to create instances of an object given any number of specific parameters. It can even create instances of objects and return them. If you have ever coded in ASP or Microsoft® Visual Basic®, you might remember the CreateObject() function that was used to instantiate and return objects based on the CLSID of a class.Activator operates on the same idea, yet uses different arguments, and returns a System.Object instance, not a variant.
In this call to Activator, you pass in as a parameter the Type that you want to instantiate. Use the Type.GetType() method to return an instance of a Type that matches the Type of the plug-in. Notice that the Type.GetType() method accepts as a parameter exactly the string that was put inside the plug-ins tag, which describes the name of the class and the assembly it resides in.
Once you have an instance of the plug-in, cast it to an IPlugin interface, and put it inside your plug-in object. A Try-Catch block must be put on this line, since you cannot be sure that the plug-in described there actually exists, or does in fact support the IPlugin interface you need.
Once you have the instance of the plug-in, add it to the ArrayList of your application plug-ins, and move on to the next XML node.
Here's the code from the application:
public object Create(object parent,
    object configContext,
    System.Xml.XmlNode section)
{
   //Derived from CollectionBase
   PluginCollection plugins = new PluginCollection();
   foreach(XmlNode node in section.ChildNodes)
   {
      try
      {
         //Use the Activator class's 'CreateInstance' method
         //to try and create an instance of the plugin by
         //passing in the type name specified in the attribute value
         object plugObject =
                   Activator.CreateInstance(Type.GetType(node.Attributes["type"].Value));

         //Cast this to an IPlugin interface and add to the collection
         IPlugin plugin = (IPlugin)plugObject;
         plugins.Add(plugin);
      }
      catch(Exception e)
      {
         //Catch any exceptions
         //but continue iterating for more plugins
      }
   }
   return plugins;
}

Invoking the Plug-ins

After all this is done, you can now use the plug-ins. One more thing is missing, though. Remember that IPlugin.PerformAction() requires an argument of type IPluginContext, which holds all the necessary data for the plug-in to do its work. You'll implement a simple class that implements this interface, which you send to the PerformAction() method whenever you call a plug-in. Here's the code for the class:
public interface IPluginContext
{
   string CurrentDocumentText{get;set;}
}

public class EditorContext:IPluginContext
{
   private string m_CurrentText= string.Empty;
   public EditorContext(string CurrentEditorText)
   {
      m_CurrentText = CurrentEditorText;
   }

   public string CurrentDocumentText
   {
get{return m_CurrentText;}
      set{m_CurrentText = value;}
   }
}

Once this class is ready, you can just perform an action on the current editor text like so:

private void ExecutePlugin(IPlugin plugin)
{
   //create a context object to pass to the plugin
   EditorContext context = new EditorContext(txtText.Text);
  
   //The plugin Changes the Text property of the context
   plugin.PerformAction(context);
   txtText.Text= context.CurrentDocumentText;
   }
}

Summary

You can see that it's pretty simple to support plug-ins in your applications. You just:
  • Create a shared interfaces library.
  • Create custom plug-ins implementing the custom interfaces.
  • Create context arguments to pass to the plug-ins.
  • Create a section in your config file to hold plug-in names.
  • Instantiate plug-ins using an IConfigurationSectionHandlerimplementer class.
  • Call your plug-ins.
  • Go home and spend some quality time away from your computer.

Reference: