ASP.NET Providers, reloaded
Note: this entry has moved.
Rob Howard wrote the
second part on the provider design pattern they are using in Whidbey, and
how to implement it in v1.x. An interesting reading. First of all, I'm
really amazed at how open these guys are to good feedback from the community.
Rob even dedicated a paragraph named "Extending configuration" that explains
why they chose a NameValueCollection
for provider
initialization over an XmlNode
, as
I suggested (I'm sure other did too, it's a pretty obvious thing to ask).
I really don't share the feeling that a NameValueCollection
is
*sooo much* easier than an XmlNode
and its added flexibility, but
at least I understand now why they did so: they expect complex providers to
have their own section handler with all the information they need to work,
which makes perfect sense!
There's a major performance issue in the implementation he suggests for v1.x, though, that has to do with the actual creation of the specific provider instance. There's a sort of mess in the naming and wording when this feature is explained. The article says:
When calling routines on the Membership class, internally it will always forwards those calls to an instance of the MembershipProvider—first creating an instance of MembershipProvider using a factory method, Instance(), and then calling the appropriate base class method on the retrieved instance.
Well, from the naming point of view, if Instance() is employed as a factory method, it should be called CreateProvider() or something like that, to denote that an instance will be created each time the method is called. And here comes the confusion, because Instance() more closely resembles the Singleton pattern rather than the Factory Method. If you think about it, there's no reason why we should instantiate a new membership object all the time. Not even the dynamic nature of providers justify this, because switching providers in the config file will cause an app restart anyway, loading the appropriate one afterwards.
And this is even more important than a mere wording because instantiating the provider dynamically requires using reflection. The abbreviated method shown in the article is:
Note that by caching only the constructor information, you're not earning much anyways. You end up using reflection at each method call anyway. So, if you convert this method from a factory method into a singleton, you directly cache the provider instance you create the first time the method is accessed. Furthermore, I'd directly move this singleton instance creation to the Membership (or similar for other provider-enabled features) altogether:
You may have noticed that the original method in the article wrongly calls a special constructor passing a specific hardcoded attribute, "connectionString":
It's obvious that by doing so the Instance()
method is no longer
generic, as it's expecting a provider to implement a specific ctor overload and
receive a connection string! What if I have an XmlMembershipProvider
?
Given the base ProvideBase
class all providers must implement, and
what is explained in the article it makes much more sense to use the ProviderBase.Initialize
method for provider initialization, as I did in the static ctor above:
Anyway, it's good that we're having these discussions. The ASP.NET community needs these concepts to turn web applications into well architected solutions, leaving the ASP spaghetti programming style behind once and for all.