Showing posts with label development. Show all posts
Showing posts with label development. Show all posts

Sunday, August 24, 2014

Intro to MEF - Part 4: Method Exports

In Part 4 of my series Intro to MEF we take a look at the basics of method exports.


Tuesday, August 13, 2013

Intro to MEF - Part 2

This is a short video Intro to MEF - Part 2 in which we examine the basics of using and AssemblyCatalog.


Friday, January 11, 2013

An Intro to MEF – Part 1

 

I’m a big fan of MEF (Managed Extensibility Framework). I think it is very easy to use and offers a lot of advantages when developing an application.  MEF was developed to be a framework to allow for extensibility in your applications.  Parts of Visual Studio (including the Entity Framework Designer) run on MEF as does the Extension Manager.  That being said, it also works very well as a Dependency Injection container. My goal is not to compare MEF to other containers (ie. Unity, Windsor Castle, NInject, etc) but to show you how to use MEF as a DI container.

As usual, you can view/download the code on GitHub.

For Part 1 we will create a simple console application that will log a message.  However, we will use MEF as a DI container to supply the ILogger implementation.  Remember, this is meant to be a very simple example.  It is definitely not meant to demonstrate how MEF should be used.

Monday, June 25, 2012

EF Entity Name Scrubbing - Part 1

Recently I've been working with a database that has some unusual naming conventions on its tables.  The naming convention consists of [(schema)_(tableName)] where 'schema' is used in place of an actual database schema.  An example is HR_Contact.  I'm not going to go into why it was done but rather what issues this presents when using the Entity Framework designer.

Here is the database that we will be working with:



As you can see, we have two HR_ tables and two IT_ tables.  When using the Entity Framework Designer several issues arise:

1. The Entities are imported with these names
2. Navigation Properties and References are created using these names
3. The Pluralization service can have issues figuring out what the appropriate pluralization would be

When you are dealing with such a small number of tables, this may not be a big deal.  But if you're dealing with 25, 50, even 75+ tables this can prove to be a real PITA.  This was such a problem that the owner of the database decided against using EF as it was too time consuming to rename everything.  Following you will see how to create an EF Designer Plugin that will do all of the scrubbing for you.

// NOTE : Before we get started, be sure that you have the Visual Studio SDK installed.  I'll be using Visual Studio 2012 RC so I'll be installing the SDK from here.

Let's begin by creating a new C# Project called EFEntityNameScrubberExtension:


Delete the default Class1.cs file and add the following assembly references:

  1. Microsoft.Data.Entity.Design.Extensibility
  2. System.Data.Entity.Design
  3. System.ComponentModel.Composition
Now create a new class called EFEntityNameScrubber and inherit from IModelGenerationExtension.  Additionally we will add two attributes to the class that will expose EFEntityNameScrubber as an IModelGenerationExtension plugin for MEF.  Your class should look like the following:

Next we will create a new VSIX Project called EFEntityNameVsix:


When the project is created a wizard will be displayed.  On the Metadata tab enter your name in the Author text box:



Under the "Install Targets" tab, add the Visual Studio versions that you will support.


Finally, under the "Assets" tab, add the EFEntityNameScrubberExtension project as a MefComponent:


Now that we have our VSIX project created and configured, set it as the Startup Project and add a few break points into the EntityNameScrubber class methods.  Once you hit F5 an Experimental Instance of Visual Studio will start up.  This can take a few minutes if it is the first time that you have used the Experimental Instance (EI).

Once the EI has started, create a new Console Application and add an Entity Data Model.  Choose the "Generate from Database" option and click Next.  Select the Sandbox database (or any database with the table prefix that we will try to create.  For now, simply add a single table to the model:












































When you click "Finish", the break point within the OnAfterModelGenerated method should be hit:









In Part 2 we will dig into the meat of the extension!

You can download the source on GitHub here.

Saturday, June 23, 2012

GetCustomAttributes Sucks

Ok so maybe the title of this post is a little harsh.  I don't really have anything against the MemberInfo.GetCustomAttributes.  I just don't like writing code like the following:


I'd prefer to do something like this:


Here is the source for the GetAttribute extension method:


You can download the full source (with tests) on GitHub here.

Saturday, September 10, 2011

Intro to Expressions

I've been doing a lot of work with Expressions recently and completely love working with them. I feel that they allow your code to be more powerful as well as more expressive. It seems to me that many developers don't use Expressions in their code though. Maybe that is because Expressions can seem daunting. If this is the case I figured some of you might like a walk through of how you can use Expressions in your daily development.

What will we be building today? How about the beginnings a validation-helper for ensuring that a field, property, or argument is not null? How often have you written the following code?



Now this code is all good and well. But at some point we might change the name of the parameter but forget to update the string that represents the name of the parameter. Instead we can use an Expression which will dynamically get the name of the member which guarantees that the argument name provided to the ArgumentNullException constructor is always correct. So instead of using a string to represent the argument name, let's use an Expression:


Nice and simple! Now for some Expression basics.

Expression Basics

As seen on msdn the System.Linq.Expression namespace can be explained as follows:
The System.Linq.Expressions namespace contains classes, interfaces and enumerations that enable language-level code expressions to be represented as objects in the form of expression trees.

The abstract class Expression provides the root of a class hierarchy used to model expression trees.

The classes in this namespace that derive from Expression, for example MemberExpression and ParameterExpression, are used to represent nodes in an expression tree. The Expression class contains static (Shared in Visual Basic) factory methods to create expression tree nodes of the various types.

The enumeration type ExpressionType specifies the unique node types.

I think that's enough of that for now. Let's dive into some code.

Following is what our method might look like without utilizing Expressions.



As we will be passing properties, fields, and method parameters into our IsNotNull method, we will be dealing exclusively with Expressions of type MemberExpression.
The best tool in the Expression toolbox is the ExpressionVisitor. In a nutshell an ExpressionVisitor handles the navigation and of an ExpressionTree (which we will talk about in more detail in my next post).

To handle extracting the MemberExpressions from our ExpressionTree we will create an ExpressionVisitor and override the VisitMember method. The VisitMember method will simply add the MemberExpression to a SortedList instance. The reason for using a SortedList is that a single Expression Tree can contain many Expressions. In some scenarios the order of which the Expressions are extracted can be very important.Here is our CustomExpressionVisitor implementation:


Now that we have a method of extracting a MemberExpression, we can implement our IsNotNull(Expression>) method. This method must do the following:
  1. Extract the MemberExpression
  2. Extract the value of the property, field, or argument from the MemberExpression
  3. Check if the value is null
  4. If null, throw an ArgumentNullException

Here is the finished code for the Validate class:


And finally here is an example of how to invoke IsNotNull:


Source code can be downloaded from github here.
























Tuesday, July 28, 2009

Windows PowerShell for developers part 2

Welcome back to Sleep Can Wait. In today's post I'll be continuing on the subject of my previous post related to the use of Windows PowerShell for developers. The continuation of this topic will show you how to extend our previously defined functions and functionality for reuse. In a future post we'll explore the use of MSBuild via PS.

To start, here is our PS profile ($profile) as we left it last time:


# Variables to hold the physical location of our current project
$projectDir = "C:\Projects\MyProject"

# Updates the current project from the SVN repository
function Update-Project
{
Write-Host "Updating project $projectDir" -ForegroundColor Yellow
svn up $projectDir
}

# Commits the current project from the SVN repository
funciton Commit-Project([string] $message)
{
Write-Host "Committing $projectDir to SVN" -ForegroundColor Yellow
svn ci $projectDir -m $message
}


So let's get down to business. There are a few things right off the bat that strike me as obvious candidates for refactoring. The first is our use of "Write-Host" with a foreground color. Let's extract a function from our use.

As is good practice let's first define our comment followed by the function:

# Write the provided text to the host with ForegroundColor Yellow
function Write-Message([string] $message)
{
Write-Host $message -ForegroundColor
}

That was quick and painless. However, it's probably a good idea to make sure the local variable $message is not null or empty and handle the error accordingly:


function Write-Message([string] $message)
{
if($message.length -eq 0)
{
Write-Error "variable [message] cannot be null" -Category InvalidArgument
$error.Clear()
break
}
Write-Host $message -ForegroundColor Yellow
}


Now that is done we can refactor our existing functions to utilize our new Write-Message function.

# Updates the current project from the SVN repository
function Update-Project
{
Write-Message "Updating project $projectDir"
svn up $projectDir
}

# Commits the current project from the SVN repository
function Commit-Project([string] $message)
{
Write-Message "Committing $projectDir to SVN"
svn ci $projectDir -m $message
}


Now we can move on to the function refactoring with some substance!
Let's first take a look at our existing Update-Project function

function Update-Project
{
Write-Message "Updating project $projectDir"
svn up $projectDir
}

As you can see this function is very simple and essentially hard-coded to always update the same project. Our first order of business is to define a new project called "MyFirstProject" in a variable $myFirstProjectDir

$myFirstProjectDir = "C:\Projects\MyFirstProject"

Now we can extend Update-Project to accept a parameter $path (along with some basic error handling)

function Update-Project([string] $path)
{
if($path.length -eq 0)
{
Write-Error "variable [path] cannot be empty" -Category InvalidArgument
$error.Clear()
break
}

svn up $path
}

We now have a more generic function which accepts a path to the directory which must be updated. We can now write a strongly typed function to utilize this generic function.

# Updates MyFirstProject
function Update-MyFirstProject
{
Update-Project $myFirstProject
}

For each new project we have we must only implement a simple one-line function to utilize existing functionality... beautiful!

Now let's refactor our Commit-Project function in the same manner

function Commit-Project([string] $path, [string] $message)
{
Write-Message "Committing $projectDir to SVN"
if($path.length -eq 0)
{
Write-Error "variable [path] cannot be empty" -Category InvalidArgument
$error.Clear()
break
}
if($message.length -eq 0)
{
Write-Error "variable [message] cannot be empty" -Category InvalidArgument
$error.Clear()
break
}
svn ci $path -m $message
}


We can now add a simple one-line function to commit MyFirstProject

# Commits MyFirstProject
function Commit-MyFirstProject([string] $message)
{
Commit-Project $myFirstProjectDir $message
}


One final modification that I'd like to make is to make our global variables constants to prevent accidental modifications. Additionally, we can now remove $projectDir as it is no longer used.

Replace "$myFirstProjectDir" with:

if($myFirstProjectDir-eq $null)
{
Set-Variable -Name myFirstProjectDir -Value "C:\Projects\MyFirstProject" -Option Constant
}

One thing to note is when defining the name of your variable "-Name myFirstProjectDir" you do not include the dollar sign ($). Additionally, we check to see if the variable is null first to prevent errors. Specifically if you do not have this safeguard PS will throw an exception stating that a variable already exists by that name.

Your complete PS profile should now look like this:

# MyFirstProject directory
if($myFirstProjectDir-eq $null)
{
Set-Variable -Name myFirstProjectDir -Value "C:\Projects\MyFirstProject" -Option Constant
}



# Updates MyFirstProject
function Update-MyFirstProject
{
Update-Project $myFirstProject
}

# Commits MyFirstProject
function Commit-MyFirstProject([string] $message)
{
Commit-Project $myFirstProjectDir $message
}

# Updates the current project from the SVN repository
function Update-Project([string] $path)
{
if($path.length -eq 0)
{
Write-Error "variable [path] cannot be empty" -Category InvalidArgument
$error.Clear()
break
}
svn up $path
}

# Commits the current project from the SVN repository
function Commit-Project([string] $path, [string] $message)
{
Write-Message "Committing $projectDir to SVN"
if($path.length -eq 0)
{
Write-Error "variable [path] cannot be empty" -Category InvalidArgument
$error.Clear()
break
}
if($message.length -eq 0)
{
Write-Error "variable [message] cannot be empty" -Category InvalidArgument
$error.Clear()
break
}
svn ci $path -m $message
}

#Write the provided text to the host with ForegroundColor Yellow
function Write-Message([string] $message)
{
if($message.length -eq 0)
{
Write-Error "variable [message] cannot be null" -Category InvalidArgument
$error.Clear()
break
}
Write-Host $message -ForegroundColor Yellow
}

Rock and Roll! I hope you enjoy this knowledge and use it as a stepping stone to more useful development!

Monday, July 6, 2009

Windows PowerShell for developers part 1

So as some of you might know I am a nerd at heart. This factors into my constant need to learn everything I can about exciting new technologies and finding a way to integrate them into my daily development life.

One of those new technologies is Microsoft PowerShell. For those of you who haven't heard of it please remove yourselves from under your respective rocks and join us in the 21st Century! If after removing yourself from under said rock you still don't know what PowerShell is then just google it! I will, however, give you one good link as a place to get started.

Now that we're all up to speed that PowerShell exists and what it is let's dive into a quick primer so you can follow along with today's lesson....

We will be utilizing a profile to store our variables and functions for future use instead of creating individual scripts. Perhaps in a future post we can discuss the use of scripts in conjunction with your profile.

Does anyone in class not have a profile? Anyone? Bueller... Bueller...
Does everyone know how to check to see if they have a profile? Well if not it is very easy to find out and very easy to create one. So, everyone follow along.

(If you are this far into the post I will assume that you know how to open PowerShell)

Do I have a profile?
To check to see if you have a profile simply open PowerShell and type:

Test-Path $profile

If this statement returns True then you have a profile. Otherwise you're out of luck and will have to create one.

How do I create a profile?
Simply type

New-Item
-Path $profile -ItemType file -Force

And abrakadabra you have created a profile! Congratulations. Now we can get to the exciting stuff!

As I mentioned above I like to find ways to integrate new technology (like PowerShell) into my daily development life. There are a few ways that I have found that have made a few mundane tasks a little easier thanks to PowerShell and the profile. However, before we can dive into that you must edit your profile.

How do I edit my profile?
To edit your profile type the following:

notepad $profile

This will open your profile in Notepad. Personally I prefer to use Notepad++ but that is entirely up to you.

It's worth stating that your profile will be loaded every time you open a PowerShell console. This means that instead of writing a few statements every time you need to accomplish a task you can write it once and reuse it. For a developer this should be nothing new. If it is new then you may want to think about picking up a development book or finding a new line of work ;-)

I know I know.... Quit your yappin' and get down to some PowerShell!

The first few tasks that I use PowerShell to accomplish are related to Source Control (I use SVN). Namely Updating and Committing. To do this we have a few things to do.

  1. Create a variable to store the directory of our project
  2. Create a function to update our project from the repository
  3. Create a function to commit our changes
Creating variables
Creating variables is very easy. We will create a variable in our profile called "$projectDir" and give it a value of "C:\Projects\MyProject"

$projectDir = "C:\Projects\MyProject"

Now wasn't that easy? Your profile should now look like this:


Now that we have our variable let's create our first function (as most people who read this post will be developers I won't go into what a function is.

Creating our first function
In point number two of our Source Control tasks we need to create a function to handle updating our project from our SVN repository.

Let's first create the function definition

function Update-Project { }

As you can see it looks somewhat like a JavaScript function except there are now parentheses. Parans are only required if the function requires parameters.

There are several things that I like to do for every function that I create. The first is to put a comment either on the first line of the body or directly above the definition stating the intention of the function. To create a comment simply prepend a # to any string:

# Updates the current project from the SVN repository
function Update-Project { }

Your profile should now look like this:

Now down to the meat of the function. If you have SVN then you may be familiar with the command svn up "C:\Projects\MyProject". If so, you will recognize this:

function Update-Project
{
svn up $projectDir
}

Adding some eye candy
As you can see, this is a great first function due to its simplicity and usability. One additional piece of eye candy that I like to throw into my functions is a statement to the console stating what is happening. We do this with the statement Write-Host like this:

Write-Host "Updating project $projectDir" -ForegroundColor Yellow

Your profile should now look like this:

Notice the -ForegroundColor parameter.
This is used to just make things look a little nicer.


Reloading your profile
Now save your profile and either close and re-open PowerShell or type ". $profile". Note that there is a period (.) and space ( ) before the dollar sign ($). This will reload your profile without having to close PowerShell. Some of you may get an error when reloading your profile stating something about PowerShell being unable to execute scripts. This is due to your ExecutionPolicy. If you are one of those people read this.
If we look at this in PowerShell we can see the following:

You can see that we got our nice yellow text and the command was executed. Disregard the 'skipped' statement (C:\Projects\MyProject doesn't actually exist on my machine ;-))

Creating a function with parameters
Now that we have our first function out of the way let's go ahead and create our second function for committing changes to our SVN repository. This function will be very similar to our Update function so I will just type it out:

# Commits changes to the current project
funtion Commit-Project ([string] $message)
{
Write-Host "Commiting $projectDir to SVN" -ForegroundColor Yellow
svn ci $projectDir -m $message
}

As you can see we do have one minor difference for this function. That is the inclusion of a parameter.

[string] $message

The "[string]" denotes that it is of type string and "$message" is the local-scope variable used store it's value.

Your profile should finally look like this:


Conclusion
All-in-all these two functions are very simple but can save you a lot of typing over the course of a few months of development if you like to use the command line. I hope you are able to take this knowledge and come up with more and better ways to utilize the power of PowerShell in your every day development.

In a future post I'll look at making our functions even more generic for those of you who work on more than one project at a time as well as how to use MSBuild with PowerShell.