Tuesday, September 02, 2008

Umbrella- collections++

As soon as the .NET framework allowed room for extension methods, this kind of thing was bound to happen. Umbrella is a 3rd party open source lib that adds extension methods and intuitive helper classes that make you wonder why they weren't there in the first place. The official codeplex site is here and the author's site is here. There are quite a few useful bits in this library for multiple purposes, but the real beauty comes through in its collections enhancements.

 

The downside of umbrella is its immaturity. To this date of september '08 I couldnt find any "official" documentation of the library per se (outside of blogs such as mine or Ayende's). Then again, maybe the unit tests speak for themselves. I sense that this project is a moving target, meaning that it is one of those open source projects in state of flux, which can make it a little hard to document.



Foreach on an IEnumerable

IEnumerable<string> items = new List<string> {"1", "2", "3", "4", "5"};
IList<string> actionItems = new List<string>();
//the old way
foreach (string s in items)
{
actionItems.Add(s);
}
//the umbrella way
items.ForEach(actionItems.Add);


Indexed foreach actions:

IEnumerable<string> items = new List<string> {"1", "2", "3", "4", "5"};
string[] actionItems = new string[5];
//the old way
int i = 0;
foreach (string item in items)
{
actionItems[i++] = item;
}
//the umbrella equivalent
items.ForEach((i, item) => actionItems[i] = item);


Pairing two lists of equal length together


IEnumerable<string> items = new List<string> {"1", "2", "3", "4", "5"};
IEnumerable<string> otherItems = new List<string> { "6", "7", "8", "9", "10" };
IEnumerable<Pair<string>> pairedItems = items.Pair(otherItems);
Assert.Equal(5, pairedItems.Count());
Assert.Equal("1", pairedItems.First().X);
Assert.Equal("6", pairedItems.First().Y);


Lazy-loading lists:

//lists that are declared but not consturcted until access-time
var list = new LazyList<int>(() => new List<int> { 1, 2, 3 });


Read-only lists:

//lists that cannot be added/removed from (without resorting to DataViews)
//ReadOnlyCollection is a part of the core .NET library, it takes an IList<T> as a constructor //argument
ReadOnlyCollection<string> readonly = list.AsReadOnly();


Lists that convert between types
(This one is intricate and I am still studying it)

//Funcs is actually a generic collection of strategies for converting between types.
//the real magic behind conversion comes from
//System.ComponentModel.TypeDescriptor.GetConverter(type).ConvertFrom(value)
IList<string> adapter = new ListAdapter<int, string>(
new List<int> { 1, 3, 4 },
Funcs<string,int>.Convert,
Funcs<int,string>.Convert);

Assert.Equal(1, adapter.IndexOf("3"));

These are the pieces that I am using within my projects, but I am only scratching the surface. I suppose when it somes to collections, you can't have too much extensibility.

Download it, use it, or simply wait until these features are folded into the .NET lib in the next release ;)

Labels:

Sunday, August 31, 2008

Linq brings back lisp memories

Often when I am searching for the most succinct way to write logic, I find myself using a declarative syntax:


public ExecutionOutcome GetValidationMessages()
{
IEnumerable<ExecutionOutcome> failedExecutionOutcomes = Context.ItemGroups
.Where(x=>x.IsValid==false)
.Select(x=>ExecutionOutcome.CreateFailureOutcome(
string.Format(
"...",
x.ItemGroupName
)
)
);
if(failedExecutionOutcomes.Count()>0)
{
return ExecutionOutcome.CreateFailureOutcome(failedExecutionOutcomes.Aggregate(string.Empty, (x,y) => x += y.Message + System.Environment.NewLine));
}
return ExecutionOutcome.CreateSuccessfulOutcome();
}


Thats relatively "cutting edge" the C# crew, but its language concept is about as old as the hills. Here is the ballpark equivalent in LISP, a language concieved in the late 50's.

(apply
(GetMessage '#),
(mapcar
(lambda (x)
(if (IsValid x)
nil,
(CreateExecutionFailureOutcome("..." (ItemGroupName x))),
)
),
(ItemGroups Context)
)
)

Lisp was a little on the cryptic side, but its true power was its declarative syntax. Lisp is a "functional language".

C# is a sequential language, with declarative extensions. Linq gives me the ability to jump in and out of "functional language" mode in C#. I find myself gradually turning back into a LISP programmer :)

One thing I wish I could do is take this kind of declarative power and apply it to SQL query plans, now that would impress me.

Tuesday, August 19, 2008

Sharepoint C# HTML Trick: Is this fluent programming or sleazy hack?

The challenge: writing custom sharepoint web-parts can be painful because there is no inline code markup. (and I'm NOT using the "smart part" )

How to write HTML using nothing but C#?
HTML is a tree just like any other AST.

This is the code I wanted to write:


<asp:Table Width="100%">
<asp:TableRow>
<asp:TableCell Width="100%" CssClass="headerRow">Alphabetical Search</asp:TableCell>
</asp:TableRow>
<asp:TableRow>
<asp:TableCell Width="100%">
<asp:GridView runat="server" Width="100%" />
</asp:TableCell>
</asp:TableRow>
</asp:Table>



This is the code equivalent (plus databinding) using fluent constructors using C#:


protected override void CreateChildControls()

{

var dataFeed = new List

{

"one",

"two",

"three"

};

var gridView = new GridView

{

Width = new Unit("100%"),

DataSource = dataFeed,

Visible = true

};

gridView.DataBind();

var table = new Table

{

Width = new Unit("100%"),

Rows =

{

new TableRow

{

Cells =

{

new TableCell

{

Text = "Alphabetical Search",

CssClass = "headerRow"

}

}

},

new TableRow

{

Cells =

{

new TableCell

{

Controls =

{

gridView

}

}

}

}

}

};

Controls.Add(table);

base.CreateChildControls();

}




Nothing earth shattering here, but I actually dont mind using this syntax. This is the result:







Do you like it?

Labels: , ,

Wednesday, June 04, 2008

Temporarily disable a button in ASP.NET

Sometimes you have a button that can trigger an asynchronous long-running process in which the http response is not a new page, but a file (excel/pdf etc).

You may want to disable the button such that impatient users don't unwittingly click the server resources into submission, but you want to re-enable it after the response is complete.

The bad news is, there is no way on the client-side to recognize when a new response has been sent (without ajax), but we can really easily set a timeout to re-enable the button after a fixed threshold of time.

Consider the following javascript function:
   function TemporarilyDisableButton(id, delay)
{
document.getElementById(id).disabled = true;
setTimeout("document.getElementById('"+id+"').disabled = false",delay);
}
The id is the ClientSideID of the button. The delay is the time in milliseconds to disable the button.
Wiring this together in your code behind is as simple as:
btnSumbit.Attributes.Add("onclick", "TemporarilyDisableButton('" + btnSumbit.ClientID + "',15000);" + GetPostBackEventReference(btnSumbit).ToString());
And the above code will disable the button for 15 seconds on the client side after the click event has fired.

Sunday, June 01, 2008

Stored procedures are not always the best tool for selecting

Working as a consultant in the past few years has given me an opportunity to view a diverse set of code bases, and see come of the common trends and habits of developers all over the map.

Literally every single codebase including (some frameworks) I have seen in the past few years bear a common design that bugs me:

READ-ONLY SQL STATEMENTS DONT NECESSARILY BELONG IN STORED PROCEDURES, THATS WHAT FUNCTIONS ARE FOR.

If you dont know what a database function is, just think of it as a parametric view. Now let me back this up some facts, and a code example that I feel justifies this argument once and for all.
  1. There is NO performance difference between a user-defined function and a stored procedure. None at all. Since the introduction of UDFs in SQL Server 2000, functions and stored procedures leverage the same compiled/cached query optimizations. In sql 2005, both stored procedures and functions can be written in the CLR environment. Since a function is guaranteed to be read-only and deterministic, in some cases a function will have a more optimal query plan than the equivalent stored procedure.
  2. A function GUARANTEES there are no side effects to the data. Since UDFs are parametric views, they are by definition deterministic and read-only opterations, so when you call them you never have to worry about any surprise side effects to your data (stored procedures cannot guarantee this).
  3. Stored procedures are not as modular and flexible as functions. In many cases, you may need to continue ETL operations on the result set from a compiled query. Every wished you could select or join from a stored procedure? Consider this scenario: I need a northwind query to retrieve employees with a HiredDate between a given date range;
    Stored procedure:
    CREATE PROCEDURE sp_GetEmployeesHiredWithindateRange
    @startDate datetime,
    @endDate datetime
    AS
    BEGIN
    select * from employees where hireDate between @startDate and @endDate
    END
    Function equivalent:
    CREATE FUNCTION fn_GetEmployeesHiredWithindateRange
    (
    @startDate datetime,
    @endDate datetime
    )
    RETURNS TABLE
    AS
    RETURN
    (
    select * from employees where hireDate between @startDate and @endDate
    )
    I call them like this:
    select * from fn_GetEmployeesHiredWithindateRange('5/25/1990','5/25/2005')
    exec sp_GetEmployeesHiredWithindateRange '5/25/1990','5/25/2005'
    and they will return the same result set. Now, imagine I have a special case where I want to combine this query with whom each employee in the original results reports to.
    With a function, I just modify the query such as:
    select * from fn_GetEmployeesHiredWithindateRange('5/25/1990','5/25/2005') e1
    inner join employees e2 on e2.employeeid = e1.reportsto
    and I am done. If I chose the stored procedure route, there is no flexible way to do this, I would need to write another stored procedure just for this case. Because you can select from the result set of functions, you can do some GREAT code reuse design on the database side that would have been a nightmare in stored procedures.
  4. Stored procedures ARE NOT the only way to protect against sql injection. I see quite a few people defending their choice of stored procedures because the rigid syntax of a sproc call protects the system against query injections. There are easier ways! Let me show you an example of how to write a UDF call that has the same level of protection:
           string sqlQuery = "select * from fn_GetEmployeesHiredWithindateRange(@startDate,@enddate)";
    DataTable dataTable = new DataTable();
    SqlCommand sqlCommand = new SqlCommand(query, sqlConnection);
    sqlCommand.CommandType = CommandType.Text;
    sqlCommand.CommandTimeout = 300;
    sqlCommand.Parameters.AddWithValue("@startDate",new DateTime(1990,5,25));
    sqlCommand.Parameters.AddWithValue("@endDate",new DateTime(2005,5,25));
    SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand);
    sqlDataAdapter.Fill(dataTable);
    return dataTable;
    I am writing ad-hoc sql inside of my C#, and parameterizing it out like a stored procedure. You know what that ends up looking like on the sql profiler?
    exec sp_executesql N'select * from fn_GetEmployeesHiredWithindateRange(@startDate,@endDate)',N'@startDate datetime, @endDate datetime',@startDate='5/25/1990',@endDate='5/25/2005'
    sp_executesql is a call from ADO.NET for running generated queries in a controlled stored procedure fashion. Subsequent calls of a similar structure enjoy the speed boost of a compiled query. This is the magic behind NHibernate's query-generation logic. In terms of SQL injection, this is every bit as safe as a stored procedure call, but with more flexibility.
To sum this all up:
  • Stored procedures are the right choice for compiled database functions with side effects (eg: inserts and updates)
  • Functions are the right choice for compiled parametric queries (eg selects)
  • When you think of functions, think of them as views with arguments.

Some other notes:
  • You cannot "order by" inside of a function, but you can in a stored procedure. You cannot order the result set from a stored procedure, but you can order the result set from a function.
  • Stored procedures have output parameters, functions don't.
  • Functions can return tables or single values, for example:
    Here is the calling syntax for a single-valued output function:
    select fn_getStartDateForEmployee(employeeID) as startDate from employees
    and here is the calling syntax for a table-valued output function:
    select * from fn_GetEmployeesHiredWithindateRange('1/1/2000','1/1/2005')

Labels:

Wednesday, May 14, 2008

VisualSVN + TeamCity + Nant + Sql Server = A Great CI solution

When you work full time as a programmer, the chances are that your codebase is a big portion of your business value.

You shouldnt just write code write code; protect it, keep it clean, version it out, and ensure its quality!
You should also be able to easily deploy and deliver that codebase in a clean, reliable automated fashion, limiting human-related error risks and giving yourself the ability to deploy quality release artifacts/MSIs/ website updates at the drop of a hat.

Its hard to argue against these ideals, but sometimes it just seems you never have the time to "do it right".

After a bit of experimentation, I've put together a solid CI system on the cheap. Its flexible, scales out well, and you could go from zero to solid build server in two day's time**.
**It may take 1 hour mechanically, but the two days factors in learning curve and any unanticipated setbacks.

The Tools:

SCM: VisualSVN Server
Cost: Free
Subversion may not be the perfect SCM, but short of its merging hassles, its a widely popular well-documented rock-solid standard, and handles true branching strategies perfectly. VisualSVN Server is a configuration of subversion straight-jacketed for windows environments. It has windows integrated authentication, and you can provision subsets of the code base to windows users and groups on a read-only/read-write basis. Https server access comes automatically as the program starts up. Their Visual Studio plugin works with Vs 2005 and 2008 flawlessly. Even though there are free alternatives for VS integration, dont be a cheapskate here, if you pony up the $50 for their VS plugin, you wont regret it.

CI: JetBrains TeamCity
Cost: Free for up to 20 unique build actions, 20 users, 3 separate build agent processes. (A generous number)
While its true that CruiseControl.NET or CIFactory gives you everything you need for CI, those options look like a scripting nightmare reminiscent of recompiling a linux kernel in comparison to TeamCity. Besides, with built-in features such as distributed build farm agents, reports, and alerting it rivals the feature set of Microsoft Team Foundation server. TeamCity integrates tightly with subversion and gives you the ability to perform "delayed commits", which is like running a hypothetical build on the server without committing any code. (This is the equivalent to "shelfing" a build in TFS). TeamCity is a platform-agnostic build server, which is nice if you have Java/rails/AIR, or other non-.NET codebases to manage.

Build Action Scripting: NANT and NantContrib
Cost: Free, small learning curve
Dont be scared, just learn it. Ant and Nant are powerful xml-based scripting languages designed specifically for building and deploying code. If you dont know nant, dont write a script from scratch, invest a focused 2-3 hours learning how it works by tinkering around with my pre-written example and you'll be ready to write your own. A well-built nant script can be executed locally or on the build server with the same results. This FAQ shows you how to add Nant-scripting intellisense into your visual studio editor to help you get started.

Build Server Database: Sql Server
Cost: If youre reading this, chances are you already have one.
TeamCity relies on a database. Out of the box, it uses a file-based database, which is not recommended for long-term stability. JetBrains recommends you migrate the server to a MySql database, but for those of us adventurous and adamant about consolidating our resources, there is experimental support** for Sql Server 2005. I'll show you how to do that.
**Its been working flawlessly for me with everything Ive thrown at it

The goal:


Basically, developers of diverse roles and platforms (web designers, QAs, architects), can update/commit to and from a common VisualSVN server over an https line, administered and secured by a "build master" role. The "build master" provisions read/write/none access to windows/AD identities and groups.

When changes have been committed to the SVN repository, a build action can be triggered on the TeamCity server. The particular action that is triggered can depend on factors such as:
  • The location of the changed files within the source tree
  • What person committed changes
During a build action, a build agent process will create a new clean temp directory, check out the latest version of the code base into the directory, and carry out a set of desired build actions. TeamCity offers some basic pre-fab build actions such as:
  • SLN 2005/2007: Build an entire solution, run NUnit tests, and report build/unit test results
  • Duplicate Finder: Report any duplicate code within a codebase
They are good starting examples, but more than likely your best option is to trigger your own custom NANT script. With custom scripting:
  • You have versions of a build routine managed source control
  • You can run a custom build script locally instead of the standard ctrl+shift-B in visual studio.
  • Its easy to configure a build agent to run a script within the source code tree.
So, if this design sounds good to you, lets go through the steps to making it happen.

0. First things first: determine what machines are going to host each application listed above and make sure they have access to one another (maybe all of the resources can be on the same server?). make a list of the build routines you desire, and when they will need to run. Make a list of your target deployment servers, their target directories, how and when deployments are going to be delivered. Create a windows identity that will host the build agent service, and make sure that this identity has write access to your intended deployment targets. The more time you invest in step 0, the easier the rest of this system will be to implement.

1. Install and configure the VisualSVN server. This is mostly a no-brainer here, it needs to be readily available to anyone who works with the code, so install this on a server that you can reach via https, or at least a secret port number. A good repository design is to use one solution per repository.

2. Import your codebase into the repository. "Check out" a local copy of your new and empty repository, paste your codebase into the trunk folder, and commit what you just checked out. Avoid adding auto-generated (dlls, resharper temp files, bin/obj folders) to the code repository. There are many great articles about getting started with subversion, here is one about getting started with VisualSVN. Once your code base has been committed to the repository, you can set up user access to the source tree.

3. Install and configure TeamCity. Run the setup on the target server. Log in to ther web server -based console. Create a VCS root, and point it to the URL of your newly created repository. The URL of your repository can be found on the VisualSVN administration console.

4. Install and configure a build agent. Use the TeamCity console to add/install a build agent, install the build agent service on the desired host server. In the MMC services console (start->control panel->administration tools->services), locate the build agent service, and bind the service's identity to that identity you made in step 0.

5. Create the TeamCity Database in your SQL Server. Just login to your target sql server and create a new database and call it 'TeamCity'. Unfortunately, TeamCity uses JDBC for connectivity and that means you can't use windows integrated authentication via this connection, you will need to create a login for this database, and give the new login "dbowner" privileges for the TeamCity database.

5. Make TeamCity talk to Sql server 2005. (One more time, sql server has "experimental support", but it has worked well for me) TeamCity has migration scripts inside of the bin folder of your installation. When the migration scripts run, they install tables and stored procedures onto the target database. For a successful migration, you will need to configure the dbmigration.properties file, and point it to the traget database, as well as the correct jdbc driver. General instructions here. To migrate into sql server, you will need the sql server 2005 jdbc driver located here at microsoft, and you should copy it to the same driver folder specified in the general instructions (\webapps\ROOT\WEB-INF\lib folder off your root TeamCity installation directory). The connection string you will be using inside of the dbMigration file should look something like:
driverName=com.microsoft.sqlserver.jdbc.SQLServerDriver
connectionUrl=jdbc:sqlserver://localhost:1433;database=TeamCity;
connectionProperties.user=user
connectionProperties.password=password

maxConnections=50
poolPreparedStatements=false
and you should change the server/user/password/port connections to your needs. You can test the connection to your server using [telnet [server] [port]] command on the command line. After youve run the migration batch file and the migration is complete, restart the TeamCity web server service (under the services console). When you re-visit the server with a browser, dont worry about the prompt to create a new user, you have not lost your build configurations.

6. Install Nant/Nant-Contrib. You will need to install these both on your developer machine and on the build server machine. When defining a new Nant build action in TeamCity, you will need to specify the path to the Nant binaries. Nant does not support building sln files in VS2005 or older, nor does it build individual csproj files, but MSBuild does. TeamCity doesnt support MSBuild triggering, but it supports Nant triggering. I bridged this annoying little gap using a custom MSBuild Nant task, a Nant task that calls MsBuild. Thats one of the many great custom tasks found in the NantContrib library. Here is an example of a simple build, test, deploy script using Nant:

<?xml encoding="utf-8">
<project name="MyProj" default="run" basedir="..\" xmlns="http://nant.sf.net/release/0.85/nant.xsd">
<property name="SchemaFile" value="C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas\NAnt.xsd">
<description>Build Script</description>

<!-- builds only the csproj, not the entire solution-->
<target name="build"
description="Compile the project using Debug configuration for more verbose error descriptions">
<echo message="Building...">
<msbuild verbose="true" verbosity="Detailed" failonerror="true" project="MyProject.csproj">
<property name="debug" value="true">
</msbuild>
</target>

<!-- deploys the project -->
<target name="deploy" depends="build, test" description="Copy production files">
<!-- Copy build results to Production folder -->
<echo message="Deploying...">
<copy
todir="\\mydestinationserver"
failonerror="true"
overwrite="true"
includeemptydirs="true"
verbose="true"
>
<fileset basedir=".">
<includes name="**/*">
<exclude name="**.resx">
<exclude name="**.cs">
<exclude name="**.csproj*">
<exclude name="**/obj/**">
<exclude name="**.pdb">
<!--<includes name="**.aspx">
<includes name="**.ascx">
<includes name="**.config">
<includes name="**.gif">
<includes name="**.jpg">
<includes name="**.mdb">-->
</fileset>
</copy>

<!-- Update connection string settings -->
<!--<xmlpoke file="Web.config"
xpath="/configuration/location/appSettings/add
[@key='ConnStringAdmin']/@value"
value="Data Source=whatever;User ID=...;" />-->
</target>

<!-- runs unit tests, if the unit tests fail, the process stops -->
<target name="test" depends="build" description="run unit tests">
<echo message="testing">
<nunit2 failonerror="false" verbose="true">
<test>
<assemblies basedir="UnitTest\bin\Debug\">
<includes name="*Test.dll">
</assemblies>
</test>
</nunit2>
</target>

<!-- default target -->
<target name="run" depends="build, test, deploy" description="build, test and deploy">
</target>

</project>
This code will build a specified csproj file, run unit tests on a specified assembly, and if everything goes well enough, it will update a connection string in the configuration file as it copies the new code base to a specified destination (maybe change over to a staging server database). For web projects, if you have any trouble running this, you may need to copy your Microsoft.WebApplication.Targets file to a local directory, so you wont have to install visual studio on your build server. More details about that little trick here.

7. Define your build actions and how they are triggered. Maybe you will run an NDepend analysis or duplication search on a weekly basis. Maybe you have a different deployment destination for a branch of a project versus the trunk of a project, or maybe you need one build action to run in succession to another, forming a chain of build actions. Here is an example of location-based build triggering syntax in TeamCity:
+:/trunk/**
-:/branches/**
This build action would be triggered by committed files to the trunk, and not by changes to the branches directory of a repository.

8. Test it out, fine tune it. You should be able to run that nant script locally, or on the build server. Once you have the kinks worked out, release it to your development team and try it out in practice.

In summary, this plan is an approach to a relatively easy-to-implement build system that can pay off big time in both the immediate and long run.

I'll be interested in hearing any variations on this plan that work for you.

Sunday, April 27, 2008

Extension Method? Visitor?

I was reading this really cool article from Scott Hanselman about a newer, smarter way to format objects into a string.

The gist of it is this: you have an extension method called "ToString(..)", with a signature like this:
public static class FormattableObject
{
...
public static string ToString(this object anObject, string aFormat, IFormatProvider formatProvider)
...
}
So what this offer us is a really cool way via reflection to format objects based on their property/field names. For example, consider the basic Person class:
public class Person
{
...
public string FirstName{ get; set;}
public decimal Money{get; set;}
}
and then you can make a call like:
Person p = new Person(3.43M, "Joe");
Console.WriteLine(p.ToString("{Money:C}, {LastName}"));
and the output would look like
3.43, Joe
^^Now thats cool! This is a really simple and powerful piece of formatting code!
But then I paused for a minute. I like the reflection and formatting, but what benefit does the extension method bring? Its a parlor trick with a slight syntactic advantage, but it also seems to unnecessarily obfuscate things. To prove my point, I extracted the meat of his code into a simple (read: "less-cool") static method.

In essense, consider the following two lines:
1. Console.WriteLine(p.ToString("{Money:C}, {LastName}"));
2. Console.WriteLine(StringFormattingVisitor.ConvertToString(p, "{Money:C}, {LastName}"));
Now the following two lines of code are functionally equivalent. Call me an old fart, but I like line #2 better, because if theres ever an issue related to the cool string formatting functionality, I can read it and see exactly where the method is defined, the first one abstracts this information away from me.
Basically, what I am seeing is that extension methods are a way to implement object visitors, but the actual identity of the visitor is hidden, such that it looks like a native method. I'm still struggling to find out why this is better than writing a plain old explicit visitor. Any opinions?

Monday, April 21, 2008

How to Export from Sql Server 2005 to a well-formed XML File

Its a shame I have to write this one. It started out innocent enough. I need some data dumped out of a query and into a well-formatted xml file for further xslt transformations.

Piece of cake, just run a "FOR XML" query on a SQL server, output the results to file, and you will have an easy-to-translate XML file, right? Not exactly...

Say this is Northwind and I want the categories joined with the products:


DECLARE @output xml;
SET @output =
(
SELECT
categories.categoryid AS '@categoryID',
(
SELECT
products.productid AS '@productID'
FROM
Products
WHERE
products.categoryid = categories.categoryid
FOR xml path('product'), type, root('products')
)
FROM
Categories
FOR xml path('category'), TYPE, root('categories')
);

SELECT @output;

Notice that I need something more powerful than RAW or AUTO mode, I want to define my own custom xml schema using the PATH syntax.
Then, I can see in the sql output window something like this:

<categories>
<category categoryID="1">
<products>
<product productID="1" />
<product productID="2" />
<product productID="24" />
<product productID="34" />
<product productID="35" />
<product productID="38" />
<product productID="39" />
<product productID="43" />
<product productID="67" />
<product productID="70" />
<product productID="75" />
<product productID="76" />
</products>
</category>
<category categoryID="2">
<products>
<product productID="3" />
<product productID="4" />
<product productID="5" />
<product productID="6" />
<product productID="8" />
<product productID="15" />
<product productID="44" />
<product productID="61" />
<product productID="63" />
<product productID="65" />
<product productID="66" />
<product productID="77" />
</products>
</category>
<category categoryID="3">
<products>
<product productID="16" />
<product productID="19" />


..you get the idea. Now I have the format and results I want, but this needs to programmatically be exported to a file. it time to switch my output from grid/text to a file... only to get this garbage in my file:


------------------------------------------------------------------------
<categories><category categoryID="1"><products><product productID="1" /><product productID="2" /><product productID="24" /><product productID="34" /><product productID="35" /><product productID="38" /><product productID="39" /><product productID="43" /><product productID="67" /><product productID="70" /><product productID="75" /><product productID="76" /></products></category><category categoryID="2"><products><product productID="3" /><product productID="4" /><product productID="5" /><product productID="6" /><product productID="8" /><product productID="15" /><product productID="44" /><product productID="61" /><product productID="63" /><product productID="65" /><prod
(1 row(s) affected)

And that is the result of a sql query for xml exported to a file. Obviously, we can't pass this to an xml parser and expect anything to work. What to do? I spent an extra 1/2 hour and ended up making a little ADO.NET program that would:
  1. Open a sql query file
  2. Connect to a sql server database
  3. Execute the query, read the full result set as an xml stream, and save a well-formatted xml document at the specified destination.
Here is the usage:

XmlExtract.exe [sql query file name] [connection string] [output file destination]
For example:
XmlExtract.exe query.sql "data source=pweissbrod0308\\sql2k5;integrated security=true;initial catalog=northwind;" "C:\output.xml"


And finally, here is the source code for my program:

using System;
using System.Data.SqlClient;
using System.IO;
using System.Text;
using System.Xml;

namespace XmlExtract
{
public class Program
{
private static string connectionString;

private static string outputFileName;
private static string sqlQueryFilename;

private static void Main(string[] args)
{
sqlQueryFilename = args[0];
connectionString = args[1];
outputFileName = args[2];

TextReader textReader = new StreamReader(sqlQueryFilename);
string query = textReader.ReadToEnd();
textReader.Close();
Console.WriteLine(query);
var stringBuilder = new StringBuilder();

SqlDataReader sqlDataReader;
using (var sqlConnection = new SqlConnection(connectionString))
{
var sqlCommand = new SqlCommand(query, sqlConnection);

sqlConnection.Open();
sqlDataReader = sqlCommand.ExecuteReader();

while (sqlDataReader.Read())
{
stringBuilder.Append(sqlDataReader.GetString(0));
}
sqlDataReader.Close();

var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(stringBuilder.ToString());

if (File.Exists(outputFileName))
File.Delete(outputFileName);

var xmlTextWriter = new XmlTextWriter(outputFileName, Encoding.UTF8);
xmlTextWriter.Formatting = Formatting.Indented;
xmlTextWriter.WriteStartDocument();
xmlDocument.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
xmlTextWriter.Close();
}
}
}
}

I hope this helps anyone with similar endeavors, feel free to paste this into snippet compiler to get a quick app up and running, or patch it into your current project for something more custom.

Thursday, April 17, 2008

A quick snippet to delete all data in sql server 2005+

Note: this is a piece of code I've lost and rewitten a few times now, maybe you'll find it handy someday.

sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all';
go
sp_msforeachtable 'ALTER TABLE ? DISABLE TRIGGER all';
go
sp_MSForEachTable 'delete from ?', '?', null, null, 'and o.name not like (''system_%'')';
go
sp_msforeachtable 'ALTER TABLE ? CHECK CONSTRAINT all';
go
sp_msforeachtable 'ALTER TABLE ? Enable TRIGGER all';
go
What it does is disable all the relational constraints and triggers in the database, then wipes the tables clean, and re-enables the constraints/triggers at the end. Very fast, even compared with the TRUNCATE command.
For some reason, every command needs to be in a batch, hence the 'go' statements.

Thursday, April 03, 2008

More thoughts on presence: Leveraging Virtualization

All too often, I run into security problems when working remotely for a client. I need to access a network resource, but since I am remote, I must wait until a sysadmin can help me or I find a less than ideal workaround.

This morning, I thought of a workaround:
Basically, I can prepare my own VM image with visual studio and all of my other development toys. I ask the sysadmin of the client's network to host my VM somewhere in his internal network. This way, I can VPN in to the client's network, access the VM via remote-desktop and viola! I have my own computer in their office.

This is a nice for me, because I have as much access as anyone else in the office. It is nice for the client (and the syadmin) because they don't need to loosen any of their security policies on my behalf.

Wednesday, April 02, 2008

Focused, yet, somewhere else...


Today has been one of the easier days for the past few weeks, its time for an update.

While its really cool to have regular subscribers asking me to post some more content, some more new ideas, I wanted to take a moment to discuss with you the skill of coping with heavy workload from multiple projects.

The picture of that disaster area is my personal office in Maine. Each screen represents a different project I'm currently working. I should have taken the picture last week when I had three laptops to strengthen my example!

Every single one of these projects is a very important obligation to me. Like any other project, there are naturally holds, emergencies, workarounds and communication overhead. This means that each project can be a bit of a hurry-and-wait scenario.

When you have multiple hurry-and-wait scenarios, you have the opportunity to context switch from your "hold" project to something else where the path is clear, to remain as productive as possible at all times. In theory, this works. In practice, CPUs will always be better at context switching than human beings, and too much switching ends up with a net result of... well.. nothing done.

People say that its essential to focus, to master the skill of doing one thing at a time, but I lack that tunnel vision; I find it very hard to cast a blind eye to any of my peripherals, because they are all important.

So I'm trying to work on a sweet spot in the balance between keeping a presence in multiple places, yet focusing my energy in one place at a time.
  • A blackberry really helps to stay attuned to multiple clients
  • Its nice to strictly enforce certain time slots to a specific project when possible
  • Better managed and longer-term projects mean less context switching on my behalf
Any tricks work for you?

Wednesday, February 13, 2008

One great poem I found:

Run your tests often,
Don't let them get stale.
Rejoice when they pass.
Rejoice when they fail.


^^I don't have the source of the original author, I wish I did. At this point in my career, I don't care
  • how haphazard the codebase may be
  • how brittle the architecture stands
  • managed/unmanaged code of any and all languages
Well-covered tests prove that the system is robust, end of story.

Thursday, January 31, 2008

Basic Property Coding Conventions in C# 3

This is a question that is arguably aesthetic: the following two classes are functionally equivalent. Which way would you prefer to write your classes?
    public class Foo
{
public string Name
{
get;
private set;
}
public Foo(string name)
{
Name = name;
}
}
or
    public class Foo
{
private string m_Name;
public string Name
{
get { return m_Name; }
}
public Foo(string name)
{
m_Name = name;
}
}
Does one stand out to you as the better way?

Labels:

Friday, January 25, 2008

Model-View-ViewModel Pattern for WPF: Yet another approach

A few days back, I posted an example here of implementing Model-View-Controller in a WPF scenario. On a side note, WPF specialist Josh Smith posted his own rendition here, which is also a very nice example and a more humorous choice of program.

A quick redux:
I was originally bamboozled by the two-way databinding features of WPF. I architected a GUI that was directly bound to my business objects.This was a bad idea for me. Why? Because my business objects do not support any form of invalid state. As the user edits the screen, he/she is directly editing a business object.

The object is in a transitional state at this point. It should be OK to allow invalidity as the user edits, but my business object will not allow invalid values, so validation and user interactivity breaks down in this approach.

I need something that stands between the GUI and the BOs. I know! Lets pull out the classic Model-View-Controller Pattern! Now I can allow the user to edit the UI as they please. When the user clicks some sort of an "Apply" or "OK" button, an event is sent to the controller, where an attempt is made to perform some of the user's changes. At the very least, validation can occur at this point; the business object will throw any exceptions and they can be caught, logged, and displayed, put on the evening news, and troops will be deployed to Norway. If there are no exceptions, the business logic is successfully performed, and the view's bindings are updated to reflect the changes in the model. This is a popular design with the web-based guys, since their views have no state.

I wasn't happy with this. Why? I'm not working web pages right now; I want two-way databinding. I have to write plumbing code to send data from the GUI to the controller? I have to write plumbing code to send changes from the model to the GUI? Wasn't the whole point of WPF databinding to get rid of this plumbing code?

The Model-View-ViewModel Pattern: Binding to Facsimile Objects

I want to dynamically bind to something that doesn't really support dynamic binding. What to do? The MVVM approach is a very attractive compromise between two-way databinding and rigid model integrity!

Before I begin, I owe references to the masters and creators of this design:
  • Dan Crevier has the complete and unabridged version of MVVM. Go read straight from the source to get the full picture. The guys is very sharp, and savvy with WPF implementation details that I may never fully understand.

I'll break it down into the key elements:
  • Forget the controller, you wont be needing it here
  • You can keep the "IView" interface from the previous example, but they are much less useful, since we will not be mocking a view in the unit tests any more. I threw them away to keep things simple.
  • The Model objects don't change.
  • The ViewModel is a "made for UI" object that represents the Business Object.
  • The UI supports direct, two-way intimate binding with the ViewModel
  • The ViewModel supports invalid states. It can easily implement IDataErrorInfo here
  • When the user "commits" the edits, the ViewModel attempts to "update" the model object that it is representing.
Here is my "Pete-brand" abstract concept of a ViewModel:

/// <summary>
/// A view model is a facsimile of a business object that is safe for databinding and invalidation
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class ViewModelBase<T> : IDataErrorInfo where T : BusinessObject
{
/// <summary>
/// The model that the ViewModel is representing
/// </summary>
protected T Model
{
get;
set;
}
/// <summary>
/// ViewModels can represent new Models that havent been created yet.
/// If the model is null, then a "construction" will occur uppon the call to ApplyChanges
/// </summary>
protected bool IsNewModelInstance
{
get { return Model == null; }
}
/// <summary>
/// Setting up for a new model instance
/// </summary>
public ViewModelBase()
{
Model = null;
}
/// <summary>
/// setting up for editing an existing model
/// </summary>
/// <param name="model"></param>
public ViewModelBase(T model)
{
Model = model;
}
/// <summary>
/// Attempt to create or edit the underlying business object
/// </summary>
public void ApplyChanges()
{
try
{
if (IsNewModelInstance)
CreateModel();
else
ApplyToModel();
UpdateViewModelFromBusinessObject();
}
catch(Exception e)
{
UpdateViewModelFromBusinessObject();
throw e;
}
}
/// <summary>
/// edit the underlying model
/// </summary>
protected abstract void ApplyToModel();
/// <summary>
/// create the underlying model
/// </summary>
protected abstract void CreateModel();
/// <summary>
/// Any changes to the model should be reflected in the ViewModel
/// </summary>
protected abstract void UpdateViewModelFromBusinessObject();

#region IDataErrorInfo Members
///<summary>
///Gets the error message for the property with the given name.
///</summary>
///
///<returns>
///The error message for the property. The default is an empty string ("").
///</returns>
///
///<param name="columnName">The name of the property whose error message to get. </param>
public abstract string this[string columnName] { get; }
///<summary>
///Gets an error message indicating what is wrong with this object.
///</summary>
///
///<returns>
///An error message indicating what is wrong with this object. The default is an empty string ("").
///</returns>
///
public abstract string Error { get; }
#endregion
}

A few key pieces here:
  • A ViewModel can be used to construct a new business object, or it can be used to edit existing ones.
  • A ViewModel exposes its own copy of public properties of the inner object, and they can indeed be as invalid and cockeyed as the user pleases.
  • When the user clicks "Apply", the ApplyChanges method will be called, which will either attempt to construct a new BO or edit an existing BO using the properties from the ViewModel. Exceptions may be thrown by the BO, and they will be caught and displayed in the normal fashion.
The program itself is functionally the same thing. The BlogEntry editor window is now tightly bound to a BlogEntryViewModel. It is the responsibility of BlogEntryViewModel to attempt to plug property changes in to the BlogEntry.

Observations along the way:
  • As you allow the user to do more and more before clicking apply, the chances of exceptions and validation problems increases. All the better reason to implement IDataErrorInfo, I suppose.
  • I am still not happy with the IDataErrorInfo interface. The ViewModel has validation, the business objects have validation, I need to find a way to reuse the validation from the BOs and not rewrite this!
  • As you allow the user to do more and more before clicking apply, the Apply() method of the ViewModel object will become more complicated as it tries to synchronize the business objects with its own state. These are a lot of Moving Parts.
  • The ViewModel and the Model contain the bulk of the intelligence, and they are very easy to isolate and test.
  • Josh Smith and others tell me that the CSLA framework handles this tie between the GUI and the BO in a graceful manner. I want to find the best solution, I will be researching here next.
The source code is a derivative of the MVC work. Download the new source code here

Wednesday, January 23, 2008

Model-View-Controller Architecture for WPF: An Approach.

Do you know that disappointing feeling you get, when you learn a new technology, you start using it, just to discover that all the examples of the new technology across the internet don't amount to a practical real-life application?

The problem with conventional WPF examples
I am far from an expert in UI, especially windows forms UI, which makes me the perfect victim for bad examples. This is the feeling that I am getting with WPF right now. Where are the best practices? Its a very impressive technology, and it makes for some very entertaining parlor tricks. We see new sample interfaces that look like video games. We see a plethora of code samples for new tricks, but few of them form to any semblance of a practical windows application.

New Technology Causes new Confusion

The other thing we get with WPF is a very dangerous period of conceptual oblivion as we try to figure out where we should define the bindings, where should we define behavior, where to draw the line between presentation and logic etc.
  • Should I use a ContentTemplate? Maybe a DataTemplate?
  • Should I define my bindings declaratively, or should I do it manually in the codebehind? If I do it in the XAML, should I use the XAML notation, or the odd new binding syntax with the curly braces?
The questions go on and on... OK I have X-teen ways to do the same thing, which way do I go?

One thing I am discovering (the hard way) is that if you just want to write a normal program, a lot of the classic design patterns are still very relevant with WPF.

The Danger of "Direct" DataBinding
DataBinding is where I got burnt.
Think about it: everywhere you look, you see examples of a WPF UI directly bound to a business object. Direct binding between the UI and a business object has some dangerous implications:
  • As I type/click etc... I am causing immediate changes to the business object. How do I undo them?
  • Since the binding is two-way and immediate, does this mean I no longer need an "Apply" button anymore?
  • What if I want to cancel what I was just doing?
I was writing a program where the UI was directly bound to my business objects. I had a textbox bound to the "Name" property of an object. My object throws an exception if its passed a name that is empty, or too big.

What happens when I type beyond this limit? As a default behavior, WPF swallows the exception! It turns out you need to write a custom binding object to display the exception to the user in a messagebox.

What is the recommended solution for databinding to objects? Your objects need to implement IDataErrorInfo. The gist of implementing IDataErrorInfo is this:

public virtual string this[string propertyName] {
get {
//find the property that matches the string "propertyName"
//check the current state of the property, is it valid?
//if its valid, return string.Empty
//if its invalid, return a formatted error
}

This code gives me a migraine headache. Why should my business objects EVER exist in an invalid state?
The recommended solution seems like an antipattern to me. Imagine that, all of your business objects implementing INotifyPropertyChanged, INotiftyCollectionChanged, IDataErrorInfo just so they can work with WPF?

But still, databinding is a very cool feature in WPF. How to leverage this without violating my model? I made a mistake, I was so focused on using new WPF tricks that I forgot how to build a good testable application.

My (current) Solution

MVC is a design pattern intended to solve the problem between separating a UI and the logic. These were the qualities I was looking to achieve:
  • "smart" business objects, they throw exceptions if you try to pass them anything invalid, or something goes wrong in an operation
  • "dumb" WPF UI that is bound in a dynamic, readonly fashion to the objects
  • The UI catches exceptions and shows them to the user in a messagebox
  • A "controller" that receives gestures from the UI and performs logic on the model
  • The controller should be very testable
  • The UI should be very mockable
  • The UI has no direct write access to anything in the business objects
The Sample Program: the cliche Blogger Application ala WPF

The sample program is here. It is a very simple, practical windows program for adding/editing/removing blog posts. The main attraction is the architecture.

The Models
The model is simple. I have a Blog that contains a collection of BlogEntries, and they are both "Persistable" meaning they have an ID and a name.
The Blog class exposes a list of its BlogEntries, but it has specialized Add/Remove methods for modifying this list.









The Views


Since I needed the view to be mockable, I set up for an interface, such as IView.
Any view must have an associated controller, and be able to update its display with the latest data. I create a view for every aspect of the program. In this case, I have a view for BlogEntries, and a view for Blogs. These views generate events that are handled by the controllers. They use BlogEntryEventArgs as arguments for the events.




The Controllers

The controllers exist to handle generated events from the views, and this is where the real business logic begins. As you can see, there is an event handler for every event in the view. One noteworthy thing here is that the controller does not need to talk back to the view for updates because the view is directly bound (in a readonly fashion) to the model. That little feature is thanks to the WPF databinding power!







Finally, The UI

The UI is two windows, one for selecting blog entries and one for editing them. Each window implements a view. Upon window construction, each window registers a controller. Button callbacks from the UI generate events sent to the controller. The windows catch and display any exceptions, and the UI is automatically updated by the direct databinding to the model.

What about tests?

How to test UI interaction without a UI? Make a "mock" of the views, and test the controller. Since our views are dumb, we can effectively test the bulk of the application using a dummy view. For example:


private class MockBlogEntryView:IBlogEntryView{...}

///
/// isolate the controller for testing
///

[Test]
public void TestCreate()
{
Blog _blog = new DummyBlogDAO().GetByID(0);
MockBlogEntryView _mockBlogEntryView = new MockBlogEntryView();
BlogEntryController _blogEntryController = new BlogEntryController(_mockBlogEntryView);
BlogEntryEventArgs _blogEntryEventArgs = new BlogEntryEventArgs(null, "blahblahblah", "New post", _blog);
_mockBlogEntryView.ThrowCreateEvent(_blogEntryEventArgs);
}
At this point, feel free to replace MockBlogEntryView with something from your favorite mocking API such as Rhino Mocks or TypeMock.NET if you are too lazy to define a dummy view.

Other Observations

Admittedly, this is yet but another simple example for a tricky concept. Does this architecture scale nicely as the complexity grows? Your mileage may indeed vary.
In my example, I have a view-per-model design, but
  • There is no real correlation at all between the number of views you have and the number of "model" objects.
  • There is no real correlation between the number of controllers you have and the number of views either. (In retrospect, perhaps I only needed one controller)
There is never a single and straight path of correctness for building any complex app; there are many right ways. I'll post again when I see how this architecture holds up to the test of time and complexity.

Download the Source Code here

Labels: ,

Sunday, January 20, 2008

PostSharp - Part 2: DataBinding support and some adjustments

Now that I have had a chance to play around with PostSharp with a few more rounds I've discovered that my old examples have some room for improvement.
Go here for my initial impressions.
  • I want my "Triggers" to occur only on property setters
  • I want the triggers to disregard any property related to reflection
  • I want to my triggers to be independent of one another (this is important)
  • I want to create a non-intrusive attribute that supports INotifyPropertyChanged
For the first two requirements, this is easy. I add some conditionals to the beginning of each MethodBoundaryAspect event. For example,


[Serializable]
public class NotNullValidator : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
//ignore calls that have no arguments, they come from reflection
if (eventArgs.GetArguments() == null)
return;
//ignore anything that isnt a setter
if (!eventArgs.Method.Name.StartsWith("set_"))
return;

if (eventArgs.GetArguments()[0] == null)
throw new ArgumentNullException(eventArgs.Method.Name);
base.OnEntry(eventArgs);
}
}

Now for the INotifyPropertyChanged functionality. I searched for an existing example, but came up empty-handed. Fortunately, there was an open source version of Data Binding support readily available at http://code.google.com/p/postsharp-user-samples/ . These examples are in VB, so I converted the code in to C#. I will be looking at adding my changes to the trunk as soon as I can get my examples to match their standards. In the meantime, this is the C# code I have been using for NotifyPropertyChanged support (based on the provided VB code):

/// <summary>
/// Custom attribute that, when applied on a type (designated <i>target type</i>), implements the interface
/// <see cref="INotifyPropertyChanged"/> and raises the <see cref="INotifyPropertyChanged.PropertyChanged"/>
/// event when any property of the target type is modified.
/// </summary>
/// <remarks>
/// Event raising is implemented by appending logic to the <b>set</b> accessor of properties. The
/// <see cref="INotifyPropertyChanged.PropertyChanged"/> is raised only when accessors successfully complete and the
/// underlying value is really changed.
/// </remarks>
[MulticastAttributeUsage(MulticastTargets.Class | MulticastTargets.Struct), Serializable()]
public sealed class SupportDataBindingAttribute : CompoundAspect
{

#region "Private Variables"
[NonSerialized()]
private int myAspectPriority = 0;
#endregion

/// <summary>
/// Method called at compile time to get individual aspects required by the current compound
/// aspect.
/// </summary>
/// <param name="targetElement">Metadata element (<see cref="Type"/> in our case) to which
/// the current custom attribute instance is applied.</param>
/// <param name="collection">Collection of aspects to which individual aspects should be
/// added.</param>
public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection)
{
// Get the target type.
Type targetType = (Type) targetElement;
// On the type, add a Composition aspect to implement the INotifyPropertyChanged interface.
collection.AddAspect(targetType, new AddNotifyPropertyChangedInterfaceSubAspect());
// On the type, add a Composition aspect to implement the IEditableObject interface
//collection.AddAspect(targetType, new AddEditableObjectInterfaceSubAspect());
// Add a OnMethodBoundaryAspect on each writable non-static property. The implementation of
// INotifyPropertyChanged.PropertyChanged needs the name of the property (not of the field), so we have to detect
// changes on the property level, not on the field level. Unfortunately, there is no rule for naming properties and
// their related fields. Even more, one property could access many fields, or gets its value out of one or
// more fields. At this point, using an enhancer to add this functionallity is only recomended, as there exixts a design
// rule, which relates one field to one and only one property and vice versa. Unfortunately, there is no compile time check available.
// Please be careful!!
// Personally, I tend to say, that implementing INotifyPropertyChanged is out of the scope of enhancers due to the
// possibility to pack logic within the properties implementation, which is never under the enhancers control.
foreach (PropertyInfo pi in targetType.UnderlyingSystemType.GetProperties())
{
if (object.ReferenceEquals(pi.DeclaringType, targetType) && pi.CanWrite)
{
MethodInfo mi = pi.GetSetMethod();
if (!mi.IsStatic)
{
collection.AddAspect(mi, new OnPropertySetSubAspect(pi.Name, this));
}
}
}
}
public int AspectPriority {
get { return myAspectPriority; }
set { myAspectPriority = value; }
}

/// <summary>
/// Implementation of <see cref="OnMethodBoundaryAspect"/> that raises the
/// <see cref="INotifyPropertyChanged.PropertyChanged"/> event when a property set
/// accessor completes successfully and the value really changes.
/// </summary>
[Serializable()]
private class OnPropertySetSubAspect : OnMethodBoundaryAspect
{

private readonly string myPropertyName;
private object myOldValue;

/// <summary>
/// Initializes a new <see cref="OnPropertySetSubAspect"/>.
/// </summary>
/// <param name="propertyName">Name of the property to which this set accessor belong.</param>
/// <param name="parent">Parent <see cref="NotifyPropertyChangedAttribute"/>.</param>
public OnPropertySetSubAspect(string propertyName, SupportDataBindingAttribute parent)
{
this.AspectPriority = parent.AspectPriority;
myPropertyName = propertyName;
}

public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
// Construct the name of the properties get-method and backup the value before the set-method is invoked.
myOldValue =
eventArgs.Instance.GetType().InvokeMember(eventArgs.Method.Name.Substring(4),
BindingFlags.GetProperty, null, eventArgs.Instance, null,
null, null, null);
base.OnEntry(eventArgs);
}
/// <summary>
/// Executed when the set accessor successfully completes. Raises the
/// <see cref="INotifyPropertyChanged.PropertyChanged"/> event.
/// </summary>
/// <param name="eventArgs">Event arguments with information about the
/// current execution context.</param>
public override void OnSuccess(MethodExecutionEventArgs eventArgs)
{
object newValue;
newValue =
eventArgs.Instance.GetType().InvokeMember(eventArgs.Method.Name.Substring(4),
BindingFlags.GetProperty, null, eventArgs.Instance, null,
null, null, null);
// Raises the PropertyChanged event, if necessary. We assume in this sample, that only value types were used.
if (myOldValue != newValue)
{
// Get the implementation of INotifyPropertyChanged. We have access to it through the IComposed interface,
// which is implemented at compile time.
NotifyPropertyChangedImplementation implementation =
(NotifyPropertyChangedImplementation)
((IComposed<INotifyPropertyChanged>) eventArgs.Instance).GetImplementation(
eventArgs.InstanceCredentials);
implementation.OnPropertyChanged(myPropertyName);
}
}
}

/// <summary>
/// Implementation of <see cref="CompositionAspect"/> that adds the <see cref="INotifyPropertyChanged"/>
/// interface to the type to which it is applied.
/// </summary>
[Serializable()]
private class AddNotifyPropertyChangedInterfaceSubAspect : CompositionAspect
{
/// <summary>
/// Called at runtime, creates the implementation of the <see cref="INotifyPropertyChanged"/> interface.
/// </summary>
/// <param name="eventArgs">Execution context.</param>
/// <returns>A new instance of <see cref="NotifyPropertyChangedImplementation"/>, which implements
/// <see cref="INotifyPropertyChanged"/>.</returns>
public override object CreateImplementationObject(InstanceBoundLaosEventArgs eventArgs)
{
return new NotifyPropertyChangedImplementation(eventArgs.Instance);
}

/// <summary>
/// Called at compile-time, gets the interface that should be publicly exposed.
/// </summary>
/// <param name="containerType">Type on which the interface will be implemented.</param>
/// <returns></returns>
public override Type GetPublicInterface(Type containerType)
{
return typeof(INotifyPropertyChanged);
}

/// <summary>
/// Gets weaving options.
/// </summary>
/// <returns>Weaving options specifying that the implementation accessor interface (<see cref="IComposed{T}"/>)
/// should be exposed, and that the implementation of interfaces should be silently ignored if they are
/// already implemented in the parent types.</returns>
public override CompositionAspectOptions GetOptions()
{
return CompositionAspectOptions.GenerateImplementationAccessor | CompositionAspectOptions.IgnoreIfAlreadyImplemented;
}
}

/// <summary>
/// Implementation of the <see cref="INotifyPropertyChanged"/> interface.
/// </summary>
private class NotifyPropertyChangedImplementation : INotifyPropertyChanged
{
// Instance that exposes the current implementation.
private readonly object myInstance;

/// <summary>
/// Initializes a new <see cref="NotifyPropertyChangedImplementation"/> instance.
/// </summary>
/// <param name="instance">Instance that exposes the current implementation.</param>
public NotifyPropertyChangedImplementation(object instance)
{
myInstance = instance;
}

/// <summary>
/// Event raised when a property is changed on the instance that
/// exposes the current implementation.
/// </summary>
//public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
//public delegate void PropertyChangedEventHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e);

/// <summary>
/// Raises the <see cref="PropertyChanged"/> event. Called by the
/// property-level aspect (<see cref="AddNotifyPropertyChangedInterfaceSubAspect"/>)
/// at the end of property set accessors.
/// </summary>
/// <param name="propertyName">Name of the changed property.</param>
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) {
PropertyChanged(myInstance, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}


How to use this? In my business object, I have:

[SupportDataBinding]
public class SomeBusinessObject
{
#region members
private string m_Name;
#endregion

#region properties

[NotNullValidator]
[Logger( LogOnEntry = true, LogOnException = true, LogOnSuccess = true)]
[StringLengthValidator(MinLength = 1,MaxLength = 10)]
public string Name
{
get { return m_Name; }
set { m_Name = value; }
}
#endregion

#region methods
public SomeBusinessObject(string name)
{
m_Name = name;
}
#endregion
}

And a test program:

class Program
{
static void Main(string[] args)
{
SomeBusinessObject someBusinessObject = new SomeBusinessObject("Pete");
INotifyPropertyChanged bindableVersion = someBusinessObject as INotifyPropertyChanged;
bindableVersion.PropertyChanged += new PropertyChangedEventHandler(bindableVersion_PropertyChanged);
try
{
Console.WriteLine("Try passing in something long");
someBusinessObject.Name = "Some name that is too long";
}
catch(Exception e)
{
Console.WriteLine("Oops! that was too long");
}
try
{
Console.WriteLine("Try passing in something too short");
someBusinessObject.Name = string.Empty;
}
catch(Exception e)
{
Console.WriteLine("Oops! That was too short");
}
try
{
Console.WriteLine("Try passing in a null");
someBusinessObject.Name = null;
}
catch
{
Console.WriteLine("Oops, that was too null...");
}

Console.WriteLine("Run a successful property change.");
someBusinessObject.Name = "123";
Console.Read();
}

static void bindableVersion_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Console.WriteLine("Handling property changed event!");
}
}

And my output:

Try passing in something long
Oops! that was too long
Try passing in something too short
Oops! That was too short
Try passing in a null
Oops, that was too null...
Run a successful property change.
OnEntry: set_Name
OnSuccess: set_Name
Handling property changed event!

Contact me if you are interested in getting my code in a downloadable solution and I will post it! Otherwise, I am going to work at getting my code on to the PostSharp user samples next week.

Friday, January 18, 2008

PostSharp - its like triggers that dont suck

**Update-- I have some amended code in a newer post located here**

Do you remember the first time you learned about triggers? Maybe you were like me, and you were initially fooled in to thinking that hidden behavior hiding behind basic operations was a good idea, only to discover its ugly side later down the road.

PostSharp brings the notion of triggers to C#, except this time I've found a safe and easy way to reuse a lot of common code with just a little bit of AOP.

Ive been pulled in to the debate about how to supplement class properties with common functionalities such as validation, logging, "NotifyPropertyChanged", Observability, and other common stuff that needs to occur with properties.

We want our Business objects to have a uniform behavior, but we often write redundant code in each property for validation, logging, databinding etc...

This afternoon I came accross PostSharp and WOW I am impressed with its potential!

Imagine this scenario:
you have a BusinessObject with a Name property.
  • the name property should not allow nulls
  • it should not allow empty strings
  • it should not allow strings longer than length of 10
  • logging should be performed before and after the property has changed
  • logging should occur if theres any exceptions that crop up inside of the depths of the Name property


public class SomeBusinessObject
{
#region members
private string m_Name;
#endregion

#region properties

[NotNullValidator]
[Logger( LogOnEntry = true, LogOnException = true, LogOnSuccess = true)]
[StringLengthValidator(MinLength = 1,MaxLength = 10)]
public string Name
{
get { return m_Name; }
set { m_Name = value; }
}
#endregion

#region methods
public SomeBusinessObject(string name)
{
m_Name = name;
}
#endregion
}

And I am done. No Kidding! Check out my little console program:

class Program
{
static void Main(string[] args)
{
SomeBusinessObject someBusinessObject = new SomeBusinessObject("Pete");

try
{
Console.WriteLine("Try passing in something long");
someBusinessObject.Name = "Some name that is too long";
}
catch(Exception e)
{
Console.WriteLine("Oops! that was too long");
}
try
{
Console.WriteLine("Try passing in something too short");
someBusinessObject.Name = string.Empty;
}
catch(Exception e)
{
Console.WriteLine("Oops! That was too short");
}
try
{
Console.WriteLine("Try passing in a null");
someBusinessObject.Name = null;
}
catch
{
Console.WriteLine("Oops, that was too null...");
}

Console.WriteLine("Run a successful property change.");
someBusinessObject.Name = "123";
Console.Read();
}
}

The output of this looks like:

Try passing in something long
OnEntry: set_Name
OnException: set_Name
Oops! that was too long
Try passing in something too short
OnEntry: set_Name
OnException: set_Name
Oops! That was too short
Try passing in a null
Oops, that was too null...
Run a successful property change.
OnEntry: set_Name
OnSuccess: set_Name

Note how the order of the attributes decides the precedence of execution. So, whats the trick? I defined those validation and logging attributes. They all inherit from OnMethodBoundaryAspect which gives me the ability to inject logic right before and after the execution of a method.
For example, here is the Null-checking property validator:

[Serializable]
public class NotNullValidator : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
if (eventArgs.GetArguments()[0] == null)
throw new Exception(string.Format("Value was null."));
base.OnEntry(eventArgs);
}
}

Here is the string length property validator:

[Serializable]
public class StringLengthValidator : OnMethodBoundaryAspect
{
public int MinLength
{
get;
set;
}
public int MaxLength
{
get;
set;
}
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
string value = eventArgs.GetArguments()[0] as string;
if(value.Length>MaxLength)
throw new Exception(string.Format("Exceeded maximum string length of {0}",MaxLength));
if(value.Length<MinLength)
throw new Exception(string.Format("Fell short of the minimum string length of {0}",MinLength));
base.OnEntry(eventArgs);
}
}

and finally, the Logging code:

[Serializable]
public class Logger : OnMethodBoundaryAspect
{
#region properties
public bool LogOnEntry
{
get;
set;
}
public bool LogOnExit
{
get;
set;
}
public bool LogOnException
{
get;
set;
}
public bool LogOnSuccess
{
get;
set;
}
#endregion

#region methods
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
if(LogOnEntry)
Console.WriteLine("OnEntry: {0}", eventArgs.Method.Name);
base.OnEntry(eventArgs);
}
public override void OnException(MethodExecutionEventArgs eventArgs)
{
if(LogOnException)
Console.WriteLine("OnException: {0}", eventArgs.Method.Name);
base.OnException(eventArgs);
}
public override void OnExit(MethodExecutionEventArgs eventArgs)
{
if(LogOnExit)
Console.WriteLine("OnExit: {0}", eventArgs.Method.Name);
base.OnExit(eventArgs);
}
public override void OnSuccess(MethodExecutionEventArgs eventArgs)
{
if(LogOnSuccess)
Console.WriteLine("OnSuccess: {0}", eventArgs.Method.Name);
base.OnSuccess(eventArgs);
}
#endregion
}

and this is just a warmup!

I found an example of INotifyPropertyChanged and IEditable property attributes in vb, I'm in the process of converting it to C# and I should have this in the next few days.

Wednesday, December 19, 2007

Generic Custom NHibernate Collections - A Second Swing

I talked about custom collections for WPF and NHibernate back here, but I wanted to mention that I made an alternative solution that ha