Subject: object instantiation madness
Posted By: GilkesM Post Date: 2/22/2007 7:41:22 PM
OK, here's what bugging me. Take for instance (no punn intended!) the Article method GetArticleByID to return an Article object by a given ID here's what happens;

The [GetArticleByID] static method of the Article class makes a call to the static method [Articles] of the SiteProvider class. This in turn returns an instance of the ArticlesProvider class. So far, so good. But the SiteProvider static method [Articles] doesn't instantiate the ArticlesProvider object using the new ArticlesProvider() method, it in turn makes a call to another static method of the ArticlesProvider class called [Instance], which in turn (I think) uses reflection (Activator.CreateInstance) to create an instance of itself?? Why would you do this??? Why not just use,
new ArticlesProvider(); ?

Also I couldn't follow this code through because the reflection method makes a call to Globals.Settings.Articles.ProviderType which, ok the Globals.Settings is a another static method that creates an instance of the WebConfigurationManager section TheBeerHouseSection  where is this class defined? because I'm not sure also where the ProviderType value is coming from. I've looked in the Web.Config under thebeerhouse section and there is an Articles part but no ProviderType attribute in the xml???? What is this ProviderType that the static method Instance is using to create an instance of itself? it seems a crazy way of doing things?
Can someone please explain what's going on because there doesn't seem to be an explanation to all this in the book??

Best Regards,

MGilkes

Reply By: englere Reply Date: 2/25/2007 11:46:15 AM
The Instance property only creates a new instance if one doesn't already exist. It one exists, it just returns a reference to that one. This is the singleton design pattern. He's using Activator.CreateInstance to allow you to use a different provider.

He made a custom config section handler, which is specified in web.config. You can do a global find to locate the code in the App_Code folder.

Reply By: rocco50 Reply Date: 3/1/2007 2:57:05 PM
I am also stuck on this. I understand the singleton pattern concept, but I can't find the "granddaddy" calling statement that makes the very first call to start the instantiation chain. Who calls SiteProvider's Articles property for example?

Also see my question on this here:
http://p2p.wrox.com/topic.asp?TOPIC_ID=54719

Reply By: Scott663 Reply Date: 3/5/2007 11:38:50 PM
I am also stuck on this Instance problem.  I have spent several days trying to figure this out, and can't make sense out of it.  One thing that I noticed is that at the bottom of page 218 there is a section from the config file with the Articles ProviderType defined (plus caching & rssitems), yet it does not exist in the final config file(?) Hmmm...

Also, can I assume that a call to SiteProvider.Articles.some_method() also initiates a call to ArticlesProvider.Instance to get the provider?  "rocco50" suggests this in his post at http://p2p.wrox.com/topic.asp?TOPIC_ID=54719, but "englere" claims that this statement is incorrect in the next post.

Can someone please explain where the Articles ProviderType comes from specifically?  And how the call to ArticlesProvider.Instance is made from SiteProvider.Articles when SiteProvider.Articles is not directly called?

Reply By: GilkesM Reply Date: 3/6/2007 7:24:58 AM
I think that in the downloaded code the web.config 'thebeersection' section has some of the attributes missing, but if you follow them through the config class they are defined as default values.

Reply By: Scott663 Reply Date: 3/6/2007 9:14:29 AM
Thanks Mark!  I see the defaults in the ConfigSection now, I was only looked in config file.

Reply By: rocco50 Reply Date: 3/6/2007 11:03:16 AM
quote:
Originally posted by Scott663
Also, can I assume that a call to SiteProvider.Articles.some_method() also initiates a call to ArticlesProvider.Instance to get the provider?  "rocco50" suggests this in his post at http://p2p.wrox.com/topic.asp?TOPIC_ID=54719, but "englere" claims that this statement is incorrect in the next post.



I set a breakpoint in TBH_Web\App_Code\DAL\SiteProvider.cs, Line 17

and here is the stacktrace:



<<<0>>>App_Code.fwtlae4u.dll!MB.TheBeerHouse.DAL.SiteProvider.Articles.get() Line 17    C#
<<<1>>>App_Code.fwtlae4u.dll!MB.TheBeerHouse.BLL.Articles.Article.GetArticles(bool publishedOnly = true, int startRowIndex = 0, int maximumRows = 5) Line 390 + 0x5 bytes    C#
<<<2>>>App_Code.fwtlae4u.dll!MB.TheBeerHouse.BLL.Articles.Article.GetArticles(bool publishedOnly = true, int categoryID = 0, int startRowIndex = 0, int maximumRows = 5) Line 411 + 0xf bytes    C#
<<<3>>>App_Web_swd_tlsl.dll!MB.TheBeerHouse.UI.GetArticlesRss.Page_Load(object sender = {ASP.getarticlesrss_aspx}, System.EventArgs e = {System.EventArgs}) Line 38 + 0x38 bytes    C#
>[External Code]    
<<<4>>>App_Code.fwtlae4u.dll!MB.TheBeerHouse.UI.BasePage.OnLoad(System.EventArgs e = {System.EventArgs}) Line 57 + 0xa bytes    C#
>[External Code]    




Based on the above, "MB.TheBeerHouse.BLL.Articles.Article.GetArticles" calls "MB.TheBeerHouse.DAL.SiteProvider.Articles.get()", and this is how the call to SiteProvider.cs, Line 17, Articles property is made.

It appears then, that MB.TheBeerHouse.BLL.Articles.Article.someMethod()  implicitly makes the get call to the Articles property of SiteProvider. So my suggestion in my previous post was correct after all?

The "instantiation" for a lack of a better term is made here for the very first time because the instance doesn't exist yet.
Reply By: englere Reply Date: 3/8/2007 9:42:44 PM
C# doesn’t have any kind of implicit object creation, but you can write your code in a manner that abstracts object creation. This can hide the object creation from the UI layer, which is often a good practice. The UI layer should not be concerned with low-level details.

The ArticlesProvider “Instance” static property is called from here in file SiteProvider.cs:

      public static ArticlesProvider Articles

      {

         get { return ArticlesProvider.Instance; }

      }

Whenever someone wants to call an instance member of the ArticleProviders class, then will first access SiteProvider.Articles to get an instance of ArticlesProvider. Also, this is a static property, which means you can call SiteProvider.Articles without having an instance of SiteProvider first.

This is not implicit object creation from a C# language perspective, but it looks like that to a UI class. You're calling a static property (SiteProvider.Articles) which doesn't need an instance in order to be called. And it will return an instance (creates one the first time) of ArticlesProvider.

Therefore, if I do this:

List<ArticleDetails> recordset = SiteProvider.Articles.GetArticles(...)

I'm calling the static property (SiteProvider.Articles), which returns an instance of ArticlesProvider. The SiteProvider.Articles getter will create an instance of ArticlesProvider before returning it if it didn’t already exist, or else it just returns a reference to that instance if it was already created.

Then GetArticles is called on the instance returned from SiteProvider.Articles. The confusing thing here is that we don't use "new" and the caller who calls SiteProvider.Articles is not saving the instance reference. He's only saving the result of the GetArticles.

As a further example, you could accomplish the same goal like this:

List<ArticleDetails> recordset = new ArticlesProvider().GetArticles(...);

The main reason Marco didn’t do it that way is because he wanted to allow a different provider to be plugged in. So the actual creation of ArticlesProvider is done using reflection instead of directly “newing” it. Also, if “new” were used without saving the reference for re-use it would always create a new ArticlesProvider class instance, which is not desired.

See page 228 for more on the SiteProvider helper class.

Eric

Reply By: rocco50 Reply Date: 3/9/2007 11:03:19 AM
quote:
Originally posted by englere
Therefore, if I do this:

List<ArticleDetails> recordset = SiteProvider.Articles.GetArticles(...)

I'm calling the static property (SiteProvider.Articles), which returns an instance of ArticlesProvider. The SiteProvider.Articles getter will create an instance of ArticlesProvider before returning it if it didn’t already exist, or else it just returns a reference to that instance if it was already created.



Eric,

I mostly understand the reflection part. The quoted part above is what I was hung up on. I didn't know that chaining a method call after a property implicitly calls the getter of the property first, which of course makes sense now that I think about it. In other words, when calling SiteProvider.Articles.GetArticles() the get() method of the Articles propery is called first, before the GetArticles() method is called. My previous thinking was that a call such as "x = SiteProvider.Articles" is needed, and I didn't see that anywhere in the code of course. And when I asked if calling the method implicitly gets the property, you said this statement was incorrect, this is what got me more confused. I guess maybe when I was using the terminology of instantiation, I was making my question hard to understand by shifting the focus back to reflection...

Anyways, regarding reflection, I am thinking the same effect could have been achieved using polymorphism instead?
Reply By: englere Reply Date: 3/10/2007 12:40:14 AM
The term "implicit object creation" implies that .NET sees that you need an object and it creates one for you. This is not functionality built-in to .NET. The property getter is an explicit method because you have to write the code for it. The fact that its hidden from the UI makes it look implicit, but I would not use that word.

This does use polymorphism. The interface defines the contract and the pluggable provider must implement the interface. You don't know beforehand which class will be created, and you need a way to create it. So that's why reflection is used here - just to create an instance of a provider specified in web.config. Reflection in this case is just a helper mechanism and not really a fundamental piece of the architecture. It's just a means to an end.

The real interesting issue is that of inheritance vs polymorphism. Marco normally prefers abstract classes for DAL and BLL bases, instead of using an interface there. This is vertical design where additional functionality is layed on top of other functionality.

The interface method, as used by providers, is the polymorphic situation of a horizontal model - each class implementing an interface has to provide 100% of the code instead of borrowing it from a base. The benefit here is that you don't depend on a common base. But the disadvantage is that you can't inherit any functionality.

But you could also mix inheritance and interfaces in some ways for a more complex design. The limit of single inheritance ends up limiting this to some extent, and I like that. Things were very muddy with multiple inheritance in C++.

Eric


Go to topic 57473

Return to index page 6
Return to index page 5
Return to index page 4
Return to index page 3
Return to index page 2
Return to index page 1