Wednesday, July 22, 2009

Creating Custom Attributes

I don't want to seem like all I ever do is bash Microsoft. Like everyone, they have their ups and downs.
Personally, I think C# and visual studio is the best toolset I've ever used in like a zillion years in IT.
Here's one small reason why. In C#, you can add attribution to object properties and methods.
Create a workflow, examine the properties, and you may see something like this:
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
or this for a WCF service:
[ServiceContract]
public interface SomeService
{
[OperationContract]


This attribution is basically metadata about the properties and meathods. Microsoft uses these for a whole list of things. One of the most obvious uses is to be able to provide meaningful information to visual editors and other 3rd party tools. An add on product, for example, that does unit testing -- nUnit, mbUnit and even Microsoft's own testing set -- uses this metadata to identify the entry points for tests and the test methods with attributes like
[TestFixture] and [TestMethod]

This is great. And it gives .Net a real professionalism over other great tools powered by Java or C++ or Php or other things.

What's even better, is that the attribution is extentable, so that you can create your own attributes. More, doing that is easy.
Simply create a class that subclasses the "Attribute" class in .net's System namespace. For example, suppose I wanted a custom attribute to indicate which properties were to be persisted to a database. This is similar to the "Serializable" attribute, but suppose I wanted to roll my own.
All I would do is this:
[AttributeUsage(AttributeTargets.All)]
public class DBSerializable: Attribute

As long as the class is in a namespace to which the target code has a reference (ie, "using") you can add
[DBSerializable]
to any property of the target class. Visual studio's intellesense will pick it up and "tada" instant custom attribution.

Ok, so I've got it... now what do I *do* with it?
Well, in this case, all I want to do is identify which properties have this attribute so that I can serialize them or not.
Since .Net's reflection pulls the meta-data about the properites, this means it pulls the attributes too -- even the custom ones!
So this becomes possible:
public static PropertyInfo[] myCustomAttributeDemo(object o) // input type of "object"
{
Type t = o.GetType(); // get the type of object
PropertyInfo[] pi = t.GetProperties(); // get the properties for the object

foreach (PropertyInfo p in pi) // for each property in the object
{
object[] q = p.GetCustomAttributes(true); // get the attributes
for (int ii = 0; ii < class="Apple-tab-span" style="white-space:pre"> // for each attribute
{
if (q[ii].GetType() == typeof(Util.DBSerializable)) // check the type
{
// do some custom logic for serializable properties
}

}
}

This can be really handy for writing really generic, reusable code. For example this was part of a generic object serializer that will generate insert statements for specific databases based on any object passed in. Doing that really cuts down on the amount of (basically) duplicate code. And it just has the small assumption that the persistable properties use the custom attribute.

Very cool.

Wednesday, July 15, 2009

annother MS rave

Seems I'm on a Microsoft-bash roll.
I guess this is a trivial thing, but it drives me batty (which isn't as much of a drive as a putt, but that's another issue).

On Windows 2008 server (... note.. the "server" part of that?) all application errrors open up cute little pop up boxes that say really helpful things like "program stopped working, click the button to stop it". And *they* *just* *sit* *there*.

remember the "server" part? Why on earth would anyone want a server poping up little useless error messages to a console that probably doesn't even have a monitor attached to it?
Do they really expect us to pay an operations person to sit on a stool in the server room and watch for the boxes to make sure they get cleared in a timely manner?
What's more, the pop-ups don't even have any options. It's not like the old famous "abort, retry error". It's just "abort".

On a PC? maybe. On a *server*? I think the guys in Redmond need more Starbucks.

And it gets better. How do you stop them from popping up each time? It's a registry setting. Not a check box on the pop up ("click here to prevent this meaningless, stupid action in the future"). No, not a control panel button. No, it's a registry setting that you need to add.

Isn't that splendid?

the MSDN thread is here:

but the correct key is:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\DontShowUI

Even better, this has to be added as a new key with a default value set to 0. Mahvalous.

/end rant

Friday, July 3, 2009

WCF

Does anyone else think that WCF is not much more than a media campaign?
The product itself just seems half-baked.

For example, suppose you want to consume a wcf service.
You end up having to first point to the service to generate the reference to it. Then you have to load the service in a browser or something to get a command line that you'll need. Then you open up a command prompt and use said command line to generate 2 files that you'll need -- one is a class file and the other is a config file.
Then it's back to Visual Studio where you need to open these and add them to your project.

Then you run the service consumer and get "Could not find default endpoint element that references contract"

(or at least, that's what I get). To be fair you don't always get this message. But if you move the service around -- like put it on your local box to write it, then move it to a devel environment to test it, then move it to QA.... good luck. It turns out that in addition to all this stuff, Microsoft generates some hidden files. Now that really irks me. I mean, if they're generating hidden files, why can't they just generate the stupid files I have to go to the dos prompt to get?
These hidden files don't always get regenerated.
In addition, the reference to the service isn't always fully qualified, which can cause issues when you move it. On top of that, studio caches a lot of binary info that it doesn't remove when you change the location of the service.

I've gotten it all to work before. But I keep wondering why Im bothering. I'm really not getting any benefit from this. I feel like MS just added wcf to put one more thing on its glossy slide show, but didn't actually finish the product.
Am I the only one who feels like that?



Wednesday, July 1, 2009

Windows WorkFun

Here's a lovely thing about windows workflow.
Suppose you want to pass in some input paramters.
That's great. And WF supports it! You create a generic dictionary of
like this:

Dictionary<string, object> ret = new Dictionary<string, object>();

now the WF framework will dutifully walk through the Dictionary, and for each string/key, it will use .Net's reflection to look for a public workflow property with the same name.

So if you create a workflow and, in the code of the class, you add:

Public string thisIsAHack

{ get { return "hack";}

set (someVar = value;}

}

then you add a Dictionary entry like this
r.add("thisIsAHack", "someDummyValue");

and if you pass the Dictionary to the workflow , then ("*ding*") the workflow property will be populated.

Ok... on one level that sounds cool.

On another level, it makes me say "what were you guys *THINKING*?"

First of all, there is no validation at all. It's very loosely coupled. So in many ways, it's a throwback to the old JScript days when all variables were "var x =" . There's no strong typing. So you have no clue until runtime whether or not things are going to actually.. you know... work? The least they could have done was provided a tool to do easy type-checkng on the inputs. Or a "is this ok" method we could call before hand that would do a test and return true/false, so we're not stuck with a runtime exception.

But, ok.

The second (minor, I'll admit) thing is that they have to be public properties. The public part I kind of understand (although it throws out data protection for things in the same namespace). But the *property* part annoys me.

I'll be honest. I love properties. I get it. But it drives me *UP A WALL* that the coding standard is:

public string SomeProp

{

get{ return _someProp;} set {_someProp = value; }

}

that code and *ZERO* value and just clutters the source. I mean please. Properties are great if you want to do some special logic with the variables. But come on. What value does it add to put a wrapper on top of the accessor, that just passes and sets the value anyway?

So far, it's not so terrible. But here's the awful part.

Ok... first of all, the workflow classes are "partial" classes. Partial classes are a sin. I hope Microsoft repents from this before God smites the world because of it. Or at least the guys who invented OOA/D smite them.

Honestly, I think Micorsoft has never liked object oriented development. All their products talk about it

I remember when VB4 came out. I still have the box. Right on it, it says that it's an "object oriented RAD" tool. Forget the fact that OO and RAD are nearly polar opposites, VB4 was about as OO as ... well... C. Yeah, it had a keyword "object" but no inheritance or dataprotection, and only had polimorphism because the data was not typed. I mean, please.

We've seen this a lot. Databound Grid controls. Need I say more? That's about as non-OO as you can get. Oh, and MVC? well, it's in the docs, but you have to work pretty hard to do it.

Alright. So partial classes are an abomination. It is an oximoron to anything object based. The whole point of a class is to put all the logic and values together. Partial classes are.. well.. not classes. They're pieces of things. At my last job, I told my team that if I ever ran across one in a code review I'd slap the developer.

(note to self: *remember to breathe*)

Now here's where it gets good. The partial class workflow is a partial to... what? Oh, you can't tell. MS locked that down. So, suppose you're walking along and you add a public (*grumble*) property to your part of the partial class. And suppose there's a name collision of some weird type with the other side of the partial class. Or.. even bettter, suppose there's a name collision with something in the hierarchy tree that.. oh yeah.. that's right, you can't see.

When you dutifully add the item to the input dictionary

r.add("Site", "somesite");

everything is great. But when you create the workflow, you'll get a runtime error with this very helpful exception message :

"Ambiguous match found".

Microsoft very clever doesn't tell you *which* property caused the ambiguous match, by the way. It's similar to some of the SQL server errors I've seen where they tell you there's a data missmatch on an insert, but don't bother to mention which column is actually mis-match.

Gee. thanks guys.

Day1

I thought I'd start this blog as a way to keeping track of all the goofy little technical issues that I encounter and (hopefully) resolve, so that I don't forget the resolution and so that others may share and benefit from my pain and run-on sentences. ..
Enjoy
--kevin