by community-syndication | Aug 8, 2007 | BizTalk Community Blogs via Syndication
Alright, so I’ve spent a lot of my time this summer (and more this fall) going to
various groups and talking about the features in C# 3.0. This is something of
a thorn in the side of my good friend Cory Smith,
who despite the fact that he is a “Visual Developer” MVP, is the staunchest Visual
Basic advocate that I’m aware of. I swear this man dreams VB, I know he blogs
VB over at AddressOf.com. As such, I thought
it was time to give all of my friends who prefer Visual Basic their fair time, or
at least some time, so this post details the new features and shows the syntax for
things. There is not exact parity to the C# feature list, but its a close thing,
so here we go.
Automatic Properties
We’ll start of with the biggest exclusion. VB does not get automatic properties,
so they are left with the more verbose version of the syntax.
Partial Methods
Partial Methods are very useful for light weight event handling in generated code.
For instance, lets assume that you had a generated class that looked like this:
Partial Class NewFeatures
Partial PrivateSub BeforeTextChange(ByVal oldText AsString, ByVal newText AsString)
End
Sub
Partial PrivateSub AfterTextChange(ByVal oldText AsString, ByVal newText AsString)
End
Sub
Private _text AsString
Public
Property Text() AsString
Get
Return _text
End
Get
Set(ByVal value AsString)
BeforeTextChange(_text, value)
_text = value
AfterTextChange(_text, value)
End
Set
End
Property
End
Class
The
partial methods BeforeTextChange and AfterTextChange are convenient extension points
should the person using your generated code needs to hook into them, but the magic
is that any of these methods which are not given implementations (both in our case
above) get compiled away.On the right you can see the Reflector disassembly
for Text property. Note that there are no calls to the partial methods, because
the compiler did not emit IL for them since there were no implementations.
Now let’s add the following short code-snippet into our project:
Partial Class NewFeatures
Private
Sub BeforeTextChange(ByVal oldText AsString, ByVal newText AsString)
newText += oldText
End
Sub
End Class
With
this added, we can go examine the Reflector disassembly again, and this time we see
something very different. Now we see the call to BeforeTextChange but still
no AfterTextChange because it still has no implementation.
Now, some important notes about this feature. Partial Methods must be Subs and
they must be Private. This is to avoid them being compiled away either changing
your interface (private) or breaking other code which depends on its results (hence
no functions).
Implicitly Typed Variables
Implicitly typed variables are not variants, this is very important so I’ll repeat
myself, Implicitly typed variables are not variants. These are strongly typed
variables which you simply forgo the need to type (as in press keys) the type (as
in the class name).
The restrictions? You must initialize the object on the same line it is declared,
so that the compiler can infer the type. Here is an example:
Dim myString
= "This is a string, I swear"
Now myString is a System.String, not a System.Object or anything else.
Object Initializers
This is a minor tweak to something which VB has always been better at than C#.
It makes a more compact version of the With syntax, at the cost of adding curly braces
into VB, so you can judge if it’s worth it for yourself.
Sub Main()
Dim ds
= New SqlClient.SqlConnection() _
With {.ConnectionString
= "Blah"}
End
Sub
For C# this feature is a god send, but C# didn’t always have With, so it’s your call
if this is truly a great feature.
Anonymous Types
Now, the addition of With as part of an object initializer is a little ho-hum, but
this is not. Enter Anonymous Types, a strongly typed object where the type is
not explicitly declared, but rather implicitly declared.
Sub Main()
Dim ds
= NewWith {.FirstName
= "Tim", _
.LastName = "Rayburn"}
End
Sub
Ok,
have I blown your mind yet? No? Well, then try this in for size… On the right is
the Intellisense you receive when you type “ds.” with this variable in scope.
The compiler has converted out simple syntax above into a full type with two properties
: FirstName and LastName. Pretty darned sexy if you ask me.
Restrictions? Of course there are restrictions. These can only be used
as private or local variables. If any other type will ever see this object them
you have to convert this to a full class. The VB compiler will let you make
these public, but it emits the type as System.Object and you loose intellisense.
Embedded Xml
This is a feature that C# 3.0 does not have, it is solely the province of Visual Basic
and I must admit, it kind of rocks. But it will also break your head the first
time you read it:
Sub CreateCityXml(ByVal name AsString, ByVal lat AsDouble, ByVal lon AsDouble)
Dim cityXml As XElement
= _
<City>
<Name><%= name %></Name>
<Latitude><%= lat %></Latitude>
<Longitude><%= lon %></Longitude>
</City>
cityXml.<City>.<Longitude>.Value = "XXX"
End
Sub
This feature has to do with LINQ to XML, the basic object of which is the XElement
class we are declaring above. You can with this embed XML directly in your VB
code. Notice there are no line continuation characters after the root node opens,
this is because it is assumed that the declare will end when the root node is closed.
Also note the use of the <% and %> like ASP and ASP.NET use to embed code into
the XML. This simple example is simply outputting variables, but there is no
reason why this couldn’t just as easily have contained a For loop or some other more
complex code.
The final line before the end of the sub shows how you can also use the XML node syntax
as if they were an object model. Now this does not include Intellisense support
for the .<tag> names, but it is still pretty slick.
Lambda Expressions
I know that Visual Basic has a tradition of being a less terse, more verbose language,
but I personally feel that VB got the short end of the stick on Lambda Expression
syntax. A Lambda expression is supposed to be a terse syntax for anonymous delegates
which also happens to be able to be explored via code if you’re using Expression Trees
(which we will not discuss here). For instance, let’s assume that you wanted
to select items from an List(of Integer) where the value was greater than 50.
You could write code like this:
Function GreaterThan50(ByVal inputList As List(Of Integer)) As List(Of Integer)
Return inputList.Where(Function(i)
i > 50)
End
Function
This is much more verbose than the C# syntax for that Lambda Expression “i => i
> 50” but I will grant you it is more readable so hopefully people who prefer VB
will prefer the VB syntax.
Extension Methods
The best feature of the .NET Framework 3.5, hands down, is extension methods.
If anyone has sold you on LINQ as the best feature, laugh at them and remind them
that LINQ is entirely based on extension methods.
What are they? Simple : The ability to add a new method to an existing type which
is only visible to those who implement your extension library.
Restrictions? Some. The biggest is that you do not get access to anything you
wouldn’t have had access to already. So creating an extension method is not
going to allow you to get access to private or internal types for a class.
Benefits? Huge! As cool as being able to add new methods to classes is,
you’ll please note I said you could extend types! This means
you can create an Interface and then provide implementation for that
interface via extension methods. In fact, that’s how LINQ is done in great part.
The .NET Framework now contains extension methods such as “Where” and “First” and
“GroupBy”for the IEnumerable interface. As such any IEnumerable can use
these, without changing the interface at all.
Very important note to those who try to stay fluent in both languages, the VB syntax
for extension methods is very different than the C# syntax, you’ll
want to pay very close attention to this.
Here are two examples, one extends a class, the other an interface:
<Extension()> _
Function ToStringNullSafe(ByVal inObj AsObject) AsString
If inObj IsNothingThen
Return
String.Empty
Else
Return inObj.ToString()
End
If
End
Function
<Extension()> _
Sub Dispose(ByVal inObj As IDisposable)
If inObj
IsNot NothingThen
inObj.Dispose()
End
If
End Sub
The first of these extension methods is something every UI developer has wished for,
a ToString function which does not blow up just because the variable is Nothing.
The second is an ingenious (if I say so myself) and beautiful hack of the IDisposable
interface. Most, but importantly not all, objects which implement IDisposable
implement a public Dispose method. Some however do not, even though they implement
it explicitly. This method will add a public Dispose method to any object which
implements IDisposable.
What if they already have one you ask? The actual method on an object always
wins out, and if there is a danger to extension methods, that is it. Should
the person who controls that type add a method which has the same name as your extension
method, your extension method becomes uncallable. A minimal risk for the incredible
power of being able to provide implementation to interfaces.
by community-syndication | Aug 8, 2007 | BizTalk Community Blogs via Syndication
Considering my history using ASP
and COM – you can imagine I’ve always been a fan of interface-based design. Of
course, I’m not a religious zealot of any sort, so I’ve always been comfortable with
the idea of abstract base classes as another perfectly valid way to create pluggable,
extensible systems. This
post is about one such pluggable system which utilizes abstract base classes – and
how that kind of design can just be stupid (not based on the concept of abstract base
classes, but just based on dumb design of such a system).
Harry has
been bugging me to post about creating classes that derive from ServiceHostBase, which
I have done quite a few times in the past year or so. The
next technical post I make after this one will be about the ins and outs of creating
a class that derives from ServiceHostBase (specifically to host workflows as WCF Endpoints),
but I’ve had this post on my chest for a while and I just had to let it out (although
as I am writing the post I am finding that it is a pretty decent introduction to ServiceHostBase
– interspersed with slight vitriol).
One of the things I strive for
whenever I design an abstract base class is to make sure that it is as simple as possible
to derive from and implement that base class. One
of the great features in Visual Studio (VS) is that via reflection VS can determine
what methods *must* be implemented for a particular base class when you build a derived
class.
Let’s take a simple example. Imagine
a base class named “Base” which is marked as abstract and which has one method, named
“VirtualMethod”. (I know this is pretty simplistic, but I feel it may be the only
way to get the WCF team at MS to understand the issue).
public abstract class Base
{
public abstract string VirtualMethod(string param);
}
Now
imagine you want to derive from that base class and create a class named “Derived”
which implements all the abstract methods of this base class. Here
is an example implementation:
public class Derived : Base
{
public override string VirtualMethod(string param)
{
Console.WriteLine(“This
should work: {0}”,param);
return “Implemented
VirtualMethod”;
}
}
A
cool feature related to abstract base classes in Visual Studio 2005 is that once you
type “public class Derived : Base”, there is smart tag hovering over the Base keyword. If
you select that smart tag with the mouse (or use the Alt-Shift-F10 keyboard shortcut
as I like to do), you get a context menu which states that it will “Implement abstract
class ’Base’” for you.
>
I
personally find the Alt-Shift-F10 shortcut to be super useful (it can also be used
to implement an interface). I also think
from a *moral* point-of-view that, when I derive from an abstract base class and use
Alt-Shift-F10 (or just manually implement *all* the abstract methods), my derived
class should *work* in whatever context the base class is supposed to work (which
is really the point of abstract base classes right?). The
whole point of marking methods “virtual” is to force the derived class implementor
to provide an override of those methods. Whatever
code uses the base class methods should work with a complete, correct implementation
of the base class (of course the C# or VB.NET compiler won’t let you complie an incomplete
implementation, but it certainly will let you compile an incorrect one).
So
what would you think if you downloaded
some library from some company which was based on some OO language which supported
abstract base classes, and you did the above steps (implementing all the abstract
methods), and then when you plugged your class into the framework for that class,
your class didn’t work? What would you
think if it didn’t work – *and* the exception
you got was a blatant lie about why your nicely implemented dervied class didn’t work?
In
fact, WCF provides such a framework (and has such an exception – you’ll just have
to keep reading for that) for creating derived classes that can plug into its framework. ChannelListeners
are the channel manager used to provide service Endpoints – that is Endpoints which
listen for incoming messages in WCF. The way you load up ChannelListeners in WCF,
in the general case, is to use a class
named ServiceHost. ServiceHost is a useful
class that enables you to associate one or more endpoints with a .NET class which
implements one or more contracts, and thus hosts one or more contracts on one or more
endpoints. ServiceHost is a really useful
class in WCF (fairly essential actually).
In
the ASP.NET/WPAS hosting scenarios, you don’t actually get to create your own ServiceHost
type – the ServiceHost is created implicitly based on your .svc file (with help from
your web.config file for the binding and potential behaviors). To create the ServiceHost,
the WCF HttpHandler actually uses a class called ServiceHostFactory, which is a fairly
typical generic Factory pattern implementation (handing out ServiceHost objects to
requestors). This features is a really
cool extensibility point of WCF, one that can be used for things ranging from controlling
Behaviors on your ServiceHost (i.e. not relying on configuration for features like
ServiceMetadataBehavior or ServiceDebugBehavior) to replacing the ServiceHost/.NET
Type pairing paradigm with some other paradigm. Steve
Maine has some good info on ServiceHost/ServiceHostFactory here.
So
more than a year ago I ventured to write my first custom ServiceHost/ServiceHostFactory
pairing. Here’s my story of that adventure. Just
to make it a little more interesting, and to see how the plumbing is put together
in WCF, I chose to derive from ServiceHostBase
and ServiceHostFactoryBase (see Steve’s article above about the choices between deriving
from ServiceHost or ServiceHostBase). So
I fired up Visual Studio and created classes that derived from ServiceHostFactoryBase
and ServiceHostBase. Using my Alt-Shift-F10 trick – this is what I end up with (after
removing the throw clauses that Alt-Shift-F10 place inside of each overriding method):
public class MyServiceHostFactory : ServiceHostFactoryBase
{
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[]
baseAddresses)
{
}
}
public class MyServiceHost : ServiceHostBase
{
protected override ServiceDescription CreateDescription(out IDictionary<string,ContractDescription>
implementedContracts)
{
}
}
Of
course at this point the code won’t compile, since I haven’t actually provided implementations. The
implemenation of CreateServiceHost is pretty easy – all I need to do there is create
an instance of ServiceHostBase. In the
typical case, your ServiceHostBase implementation will have a constructor that takes
both of the arguments passed to CreateServiceHost. The
OOB implementation (ServiceHost) uses the first argument to figure out what .NET Type
should be used to implement the service Endpoints around, and uses the second argument
as list of base Uris that relative Uri’s can hang off of the base addresses (assuming
the Endpoint’s transport channel matches the scheme of the base Uri). So
that’s pretty easy. I’ll store those
two parameters in instance fields on the MyServiceHost Type, as we’ll need them later.
The
interesting part here is implementing ServiceHostBase::CreateDescription. CreateDescription
is really the key to making your ServiceHostBase implementation work within the WCF
infrastructure. From the look of the
return value (ServiceDescription) you might get the mistaken idea that the ServiceDescription
is only used by WCF to publish metadata (assuming metadata publishing is enabled on
your Service). This is really pretty
far from the truth. The instance of ServiceDecription
returned from your ServiceHost (as well as the out parameter – the generic dictionary
of strings and ContractDescriptions) is used for more than just metadata publishing. It
is used by the WCF dispatching layer to route messages received via the Channel layer
down to the Service layer (the piece we are trying to implement). Creating
a valid ServiceDescription and returning the list of implemented contracts is essential
for making your ServiceHostBase-derived class work.
So
let’s assume I create a valid return value and out parameter for CreateDescription
(the next post will get into the necessary detail on how exactly to accomplish that). Once
I do so, notice that there are no more virtual method to implement from ServiceHostBase.
Next,
I need to get my custom ServiceHostBase derived class loaded by WCF. In
the typical WCF hosting scenario in IIS there is a .svc file. The
.svc links to the “Service Type” – the .NET Type that WCF will use as the basis for
the endpoints exposed via the Uri ending in .svc. Here
is a typical example:
<%
@ServiceHost Language=C# Debug=”true” Service=”MyService” CodeBehind=”~/App_Code/Service.cs”
%>
In
the IIS hosting case, the value of the Service attribute from the ServiceHost directive
is passes as the parameter to the ServiceHostFactory:CreateServiceHost and to the
typical contstructor of ServiceHost.
To
load your own custom ServiceHostFactory all you need to do is add a Factory attribute
to the ServiceHost directive. Like this:
<%
@ServiceHost Service=”MyService” Factory=”MyServiceHostFactory” %>
When
I do all this and browse to the URL for the Service, I get this lovely exception in
the browser:
For search engine purposes – the exception/lie is “InitializeRuntime requires that
the Description property be intialized” (this part isn’t a lie) – “Either provider
a valid ServiceDescription in the CreateDescription method or override the InitializeRuntime
method to provide an alternate implementation”.
So
I begin to scratch my head (this is me retelling the story when I first wrote this
code oh-so-long-ago). I
generally always assume that when something like this happens, *I’ve* done something
wrong. So I assume my instance of ServiceDescription
must be invalid, since I *definitely* implemented the abstract methods from ServiceHostBase.
Here
is where things get ugly. I spent an afternoon looking through Reflector to
figure out where I had gone wrong. I
even went to the trouble to delegate to an instance of ServiceHost to get what I knew
to be a valid ServiceDescription. Once
I had done that and I was still getting the same exception, I began to think it wasn’t
*my* implementation of CreateDescription, but something else. This
of course (about 4 hours later) led me down another Reflector expedition into what
ServiceHost was doing that I wasn’t.
Finally
after another hour or so – I stumbled upon it. In
the *constructor* of ServiceHost (not ServiceHostBase mind you – but WCF’s OOB implementation
of ServiceHostBase) there is a call to InitializeDescription. InitializeDescription
calls another method, which in turn sets the ServiceHostBase.description field (which
is *private* BTW so I couldn’t set the value myself) to the return
value of the call to CreateDescription.
So
the *only* way to make a ServiceHostBase derived class work inside of this infrastructure
is to call a “magic” method inside of your ServiceHostBase constructor. Failure
to call IntializeDescription will lead to complete failure when implementing a derived
class of ServiceHostBase.
So
now that I have all my pent-up frustration out – what are the key points here?
1) This
is a stupid design – if I implement all the abstract methods of an abstract base class
my class should work. Period. Unless
there is some super compelling reason – this should also be the case with interfaces
(see ISerializable for what I would consider to be a valid exception to this rule
where you must implement a special constructor for deserialization purposes).
2) WCF
has no such special reason. In fact,
if you look at the implemenation of InitalizeRuntime, all it does is check to see
if the value of the Description property is null or not (the Description property
is a public read-only property on top of the ServiceHostBase.description field). If
it is null, the stupid exception I showed above is displayed. Are
you telling me ServiceHostBase:InitializeRuntime couldn’t reasonably add one line
of code to call CreateDescription after discovering that the property is null. And
*then* throw this exception after that call returns null? Or
the Description property itself could be responsible for calling InitializeDescription
if the field was null (this was Harry’s suggestion).
So
basically this means the exception I got is a blatant lie. I
did provide a perfectly valid ServiceDescription from my CreateDescription method. It’s
just that ServiceHostBase never calls CreateDescription. Instead
– in my derived class – in my constructor – I have to call another method (InitializeDescription)
which then in turn will cause the description field to be properly filled in with
the return value of my totally correct/valid ServiceDescription (which I have to rely
on since the description filed on ServiceHostBase is private). Which,
mind you, I had created 6 hours before
I discovered the magic InitializeDescription method.
Please
folks (at MS and elsewhere) don’t design abstract base classes that rely on magic
methods to work correctly. It makes me
testy. It’s dumb. What
else can be said about it? How about – IT’S DUMB (ahh – I feel better
already).
Alt-Shift-F10
plus actually implementing all the methods correctly should be enough (barring some
real circumstance which might make making a magic method necessary – and if that’s
the case – document the hell out of it).

Check out my BizTalk
R2 Training.