Skip to content


News: Most Valuable Blogger @dzone

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

I am glad to inform you that I have been presented the badge MVB – Most Valuable Blogger at one of the famous .NET sites DZone towards my contribution to the industry. In this event, you will read my blogs & articles on DZone website apart from my own website. What it also means is you will see what I am currently doing, reading, developing, and what I recommend on Dzone and its affiliated websites.

I am thankful to Mitch Pronschinske (DZone Editor-In-Chief) and his other team members for giving me this honour.

 

image


Related Posts:

  • No Related Posts

Posted in Off-track.

Tagged with .


CInject – Extending code injection with plugins

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

If you are new to CInject, please consider reading this article

Plugins? Yes, you can now create CInject plugins to customize CInject for your needs.  To develop a plugin, you do not need to master C# language, or understand Reflection, or Mono Cecil.  All you need to know is concepts of inheritance, and a little about working of CInject.  So lets not beat around the bush and get to the point.

How do I create a plugin?

To create your own plugin, create a Class Library project in Visual Studio 2010.  Let’s name the project as CInject.Plugin.Sample. The project output will be an assembly whose name should match the format

CInject.Plugin.*.dll

 

image

 

So lets right click the Visual Studio Project and click on Properties. In the tab “Application”, change the Assembly Name to CInject.Plugin.SamplePlugin. Next, we need to add reference to some assemblies

Adding Project References

  • CInject.PluginInterface.dll – This assembly is shipped with CInject and exposes interface IPlugin that we need to implement
  • System.ComponentModel.Composition.Codeplex – This assembly can be downloaded from CodePlex (MEF), or from the CInject package.
  • System.Drawing – This assembly is required for implementing Plugin Menus.
  • System.Windows.Form – This assembly is required as CInject is a Windows Application

image

Implemeting IPlugin

 

Let’s create a class called SamplePlugin.cs.  The name of the class has nothing to do with the name of the plugin so you can name it as you want.  This class needs to be decorated with Export attribute of MEF framework (found in namespace System.ComponentModel.Composition).  The Export attribute has 2 constructors, but for CInject we will use the constructor that takes one parameter i.e. Type.  So we decorate it with

[Export(typeof(IPlugin))]

Since we are developing the plugin for CInject, the class needs to implement the interface IPlugin and should have a valid Name, Version, Menu and an implementation of OnMessageReceived and HandleError.  Let’s understand the significance of the each member of IPlugin interface

  • Name – This is the name of the plugin [To be used in the next release]
  • Version – This is the version of the plugin [To be used in the next release]
  • Menu – If you want your plugin to display a Menu you can implement it; othewise, you can choose to return a NULL value (as shown in the code below)
  • OnStart – This method is called when the plugin is loaded into memory
  • OnClose – This method is called when the plugin is unloaded from the memory. This method should clean up the resources from the memory to allow successful closure of the application
  • OnMessageReceived – This method receives the events & messages from the CInject application. This method should ideally contain logic to handle the events and perform some plugin related logic
  • HandleError – Any technical unhandled errors raised while execution of OnMessageReceived, OnStart, and OnClose will be caught in HandleError method. This method should not throw any exception and should be written very carefully

 

SamplePlugin code
  1. using CInject.PluginInterface;
  2. using System.ComponentModel.Composition;
  3. namespace CInject.Plugin.Sample
  4. {
  5.     [Export(typeof(IPlugin))]
  6.     public class SamplePlugin : IPlugin
  7.     {
  8.         public string Name
  9.         {
  10.             get { return “SamplePlugin”; }
  11.         }
  12.         public string Version
  13.         {
  14.             get { return “1.0″; }
  15.         }
  16.         public System.Windows.Forms.ToolStripMenuItem Menu
  17.         {
  18.             get
  19.             {
  20.                 return null; // NULL – plugin does not have any menu
  21.             }
  22.         }
  23.         public void OnMessageReceived(EventType eventType, Message message)
  24.         {
  25.             // Implement logic for Message Received from CInject Application            
  26.         }
  27.         public void HandleError(System.Exception exception)
  28.         {
  29.             // This should never throw any exception            
  30.         }
  31.         public void OnStart()
  32.         {
  33.             // Should read configuration, initialize variables, etc
  34.         }
  35.         public void OnClose()
  36.         {
  37.             // Should clean up the memory resources
  38.         }
  39.     }
  40. }

 

Handling the events & messages

 

There are multiple events that CInject application raises. Let’s have a quick look at them

  • ProcessStart – Called when overall processing starts
  • MethodInjectionStart – Called before an assembly method is injected
  • MethodInjectionComplete – Called after an assembly method is injected
  • ProcessComplete – Called when overall processing completes
  • TargetAssemblyLoaded – Called when a target assembly is loaded
  • InjectionAssemblyLoaded – Called when an injection assembly is loaded
  • ApplicationStarted – Called when CInject application has started
  • ApplicationClosing – Called when CInject application is closing
  • Error – Called when an error occurs within CInject application.  This is different from HandleError that handles the unhandled exceptions raised by plugin code

 

OnMessageReceived code
  1. public void OnMessageReceived(EventType eventType, PluginInterface.Message message)
  2.         {
  3.             switch (eventType)
  4.             {
  5.                 case EventType.ApplicationClosing:
  6.                 case EventType.ApplicationStarted:
  7.                     break;
  8.                     // Here Error property will be null
  9.                     // Only Result will be non-null  
  10.                     MessageBox.Show(“I received a injection related message: “ + message.Result);
  11.                 case EventType.TargetAssemblyLoaded:
  12.                 case EventType.InjectionAssemblyLoaded:
  13.                     break;
  14.                     // Here Error property will be null
  15.                     // Only Result will be non-null with injector/target assembly path
  16.                     MessageBox.Show(“I received a injection related message: “ + message.Result);
  17.                 case EventType.MethodInjectionStart:
  18.                 case EventType.MethodInjectionComplete:
  19.                     // Here Error property will be null
  20.                     // Expect Target, Injector will be non-null
  21.                     MessageBox.Show(“I received a injection related message: “ + message.ToString());
  22.                     break;
  23.                 case EventType.ProcessComplete:
  24.                 case EventType.ProcessStart:
  25.                     // Here Error property will be null
  26.                     // Expect only the Result to be non-null
  27.                     MessageBox.Show(“I received a process related message: “ + message.Result);
  28.                     break;
  29.                 case EventType.Error:
  30.                     MessageBox.Show(“I received an error message: “ + message.Error);
  31.                     break;
  32.             }
  33.         }

 

Compiling and deploying

You can now compile the class library to create a plugin named CInject.Plugin.SamplePlugin.dll and deploy it in Plugins sub-folder in the CInject application.  The CInject application automatically scans for

  • Assemblies that match the name pattern CInject.Plugin.AnyNameHere.dll
  • Searches for IPlugin implementation(s) with Export attribute within the searched assembly CInject.Plugin.AnyNameHere.dll
  • Loads them in memory and raises events OnStart, OnMessageReceived (with EventType ApplicationStarted) in same order
  • Unloads them from memory when application is closed and raises events OnClose, OnMessageReceived (with EventType ApplicationClosing) in same order

 

image


Related Posts:

Posted in Applications, C#, Open Source.

Tagged with , , , , .


Silverlight Best Practices (Part 4 of 4)

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

This is in continuation to my previous post Silverlight Best Practices – III, where the focus was what should be and what should not be done while developing a Silverlight Application. It was purely from a developer’s perspective.  In this post, we would consider designing the ‘Data Access Layer’

Designing Data Access Layer

In most of the web applications, data access layer comprises of 3 components:

  • Utilities – that help in accessing data components. Example, converters and alike
  • Data components – core components that access the data sources
  • Service Agents – this is an additional layer (proxies) over the services that are called from DAL. Mostly done to bring an additional isolation, entity mapping, or service-specific conversions.

Here, we will concentrate on ‘Data Components’ as the other two components are relatively easier to design and readily available as well or tools can generate them too. 

Managing Connections

Which connection remains open/closed should be monitored by a single interface. All calls should be redirected to a single function which would manage opening, closing of a connection and its timeout.  Connections can be cached for smallest duration of time to increase performance – however, security should of sensitive information like hostname, password should be taken care of as well.

The application should also take care that the fan-out does not reach.  This will ensure that no user gets a timeout error.

Design should enable switching between two replicas of data sources. This is most important during maintenance shutdown, or release of a newer version of application, or when database crashes. 

Exception Handling

DAL should ideally handle all exceptions and should not crash in any scenario; however all CRUD operations MUST be handled by DAL.

Exceptions concerning data access (data source unavailable, timeout, etc) should be handled by DAL; while other business related errors should be returned in an Error object in a serialized format.

Profile for best performance

In Internet applications DAL is the most accessed-by, making it prone to crashes and security risks.  Profiling of DAL is must to gauge the impact of high number of concurrent users.  Also, in such scenario DAL should be prevented against attacks from hackers.  Any other source of access should be give least privilege and only the web application should be at a higher privilege.

Consider using Batch Processes to reduce round-trip to database server.

Managing data

One of the common problems seen in many projects while doing profiling exercises is degraded performance due to improper data handling.  So let us see some important guidelines:-

  • If the system involves lot of documents and image storing – prefer to store them in BLOB, than on a file system
  • Avoid Outer Joins wherever possible
  • Use of cursors should not be preferred – use in-memory temporary tables instead.
  • Open connections as late as possible.
  • Use XML pameters for bulk inserts or updates – this will save execution time.
  • Use parameterized SQL statements and typed parameters to mitigate security issues and reduce the chance of SQL injection attacks succeeding.
  • Do not use string concatenation to build dynamic queries in the data layer.
  • Use typed parameters as input values to the procedure and output parameters to return single values.
  • Use optimistic concurrency with non-volatile data to mitigate the cost of locking data in the database

 

Dynamic Queries or Stored Procedure

 

  1. For a small footprint application with lesser clients and few business rules, prefer Dynamic Queries. IF NO, STEP 2
  2. Larger application, multiple clients – abstraction can be at
    1. Database level in Stored Proc – minimal code changes
    2. DAL using patterns  - best till the schema does not change, can be debugged
    3. DAL using ORM – best till the schema does not change, can be debugged

 

ADO.NET Services

I would suggest a very good tutorial on MSDN. Click here to read through.

This concludes the series of best practices articles on Silverlight. Thanks for reading them through!



Related Posts:

Posted in Microsoft .NET, Silverlight.

Tagged with , .