Posts tagged with 'IL'
I just open-sourced a tool that I wrote that I've been using internally at Zimbra (previously Telligent) for almost a year. It's an ugly little tool that I wrote out of frustration, but I've gotten so much use and time savings out of it that I thought I would share it. It's called SQL Profiler Query Cleaner.
SQL Profiler is a great tool to show you exactly what SQL is being executed, along with the parameters. This is especially useful when debugging, because sometimes you aren't sure what SQL is being executed. However, often times I will find myself having to pull that SQL+parameters out of SQL Profiler and paste it into SQL Server Studio in order to analyze, tweak, debug, etc. However, notce the output of SQL Profiler (bottom part of the screenshot):
The SQL string is there, but there are escaped characters. The parameters and arguments are there, but they're first declared, then assigned, "doubling" the syntax. It executes fine in SQL Studio, but if there's a syntax error, you can't really pinpoint exactly where in the query the error is, because you have to unescape the strings, manipulate the parameters (in two spots), and it's just time-consuming if you're doing this a lot (which I was).
So, fire up Sql Profiler Query Cleaner, paste the SQL Profiler output into the top text box, click the "Clean" button, and the bottom text box will have a more SQL Studio friendly query. I pasted the query from the above screenshot, and this is the result:
Please let me know if you find this useful. My guess is that if you use SQL Profiler a lot, this tool will save you some time.
I was recently updating an ASP.NET project from MVC 4 to MVC 5 and I ran into some issues while compiling. The PostSharp post-compiler was complaining that it couldn't find a 4.0.0.0 version of an assembly.
I had the correct bindingRedirects in the Web.Config. I'm not completely clear on how and why bindingRedirects work, but as I understand it, this will redirect the compiler looking for a certain version of an assembly to another version of an assembly. Something like this:
I wasn't the first to run into this issue: I came across a similar question in the PostSharp support forums. PostSharp needs to be told where to look for the bindingRedirect confirmation (since PostSharp isn't specific to the web, the configuration could conceiveably be in app.config, web.config, or some other config file). So, I merely needed to add a PostSharpHostConfigurationFile property to the csproj file, as shown in the PostSharp documentation. After that, everything worked fine.
One of my core motivations for using AOP is that it can bring the single responsibility principle to places that would otherwise be difficult or impossible without AOP.
To review, here's the single responsibility principle in a nutshell:
A class should have one, and only one, reason to change.
Why is this a good principle? I think that the ObjectMentor white paper on SRP [PDF] sums it up very nicely, but basically if you have multiple concerns in a single class, those concerns become tangled together. This isn't a huge problem until you need to make a change (which never happens in software, right?). If I want to change responsibility A, I now have to involve the code for responsibilities A and B (and C and D, etc). All these responsibilities are coupled. If I make a change, I could break the class in multiple ways, affecting every one of the coupled concerns (unless I have a good suite of unit tests, which is unlikely if I have a very coupled set of concerns).
To avoid coupling, a good rule of thumb that I use is to describe what a class does in one sentence. If I have to use the word "and", then it's probably doing too much, and should be split into 2 or more classes.
Examples:
- PersonRepository: this class persists person objects to a database. Check! There's no "and", so this class is only doing one thing.
- BillPayService: this class submits transactions to the payment processor and stores payment history in an audit database. Bzzt! It's doing two things. Maybe I should consider a PaymentProcessorService and a PaymentHistoryRepository refactor.
- AccountController: this class routes the user to the appropriate account views (and logs any invalid request errors). I'll stop belaboring the point and leave this an an exercise to the reader.
This is the last post of a series of posts about using ASP.NET's ActionFilter.
The last method that you can override in an ActionFilter is OnResultExecute, which runs after the result of a controller action has been executed.
An argument of type ResultExecutedContext gets passed in to OnResultExecute. It's not wildly different from ResultExecutingContext, except that instead of a "Cancel" member, you get a "Canceled" member, which just tells you after the fact if the action was cancelled or not. You can still access HttpContext, the Controller object, the Result, the RouteData, etc.
I can't really create another kitchen sink view like I could with the previous blog posts, because the ActionResult (usually a ViewResult) has already been executed. (I could still write to the Http Response, but that would be a little tedious).
Since OnResultExecuted can't output to the view, it's somewhat limited in its general usefulness. Logging, of course, can still be done here. Last minute changes to the HttpResponse might be a good use of this filter. You can still handle some exceptions, though using a HandleErrorAttribute filter might be a better idea for that.
I've been trying on and off to figure out Mono.Cecil, and so far it's not very encouraging. It's a bit above my pay grade, it seems.
But all is not lost: I came across a tool while browsing NuGet called FireWeaver. It sits on top of Mono.Cecil, which means it does its work after compilation. It provides you with a way to replace a class with an entire other class. So it's not exactly intercepting or proxying classes, the way other AOP frameworks do: it flat out replaces it and is "essentially duct typing(sic) the entire object definition". I don't know if that's supposed to be "duct taping" or "duck typing", but I rather like the term "duct typing".
Here's a quick example of how it works, taken from the FireWeaver CodePlex site. First, I added FireWeaver with NuGet. Then I created a console app like this:
Compile and run as normal and here's the output:
Next, run the FireWeaver.Bootstrapper.exe tool against your assembly/assemblies. In my case, my Replace class is in the same assembly as the class it's replacing, so my arguments are identical, but you could certainly specify another assembly as the second argument:
And here's the output of the console app after I ran FireWeaver.
And here's what the assemblies look like (decompiled) before and after FireWeaver. Warning, your head may explode:
I'm just as confused about Cecil looking at these JustDecompile screenshots as I was before. But I assure you, it does work.
There's definitely some potential here, since this is a pretty easy tool to use, and integrating FireWeaver into your build script(s) shouldn't be too difficult if you don't want to hit the command line after every build. And it almost looks like pure duck typing brought to C#.
But this could also lead to some really wild code if you aren't careful with it. "Dogs and cats living together, mass hysteria" code.