tag:blogger.com,1999:blog-175673862024-03-07T13:54:20.413-05:00Programmer`s thoughtsI see this as a convenient place for me and my fellow software developers to share our thoughts.Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.comBlogger106125tag:blogger.com,1999:blog-17567386.post-26231776474725432011-07-20T11:44:00.001-04:002011-07-20T11:44:34.206-04:00What’s Wrong with ASP.NET Web Forms?<p>What a great description of all the deficiencies of ASP.NET Web Forms! The following is an excerpt from <a href="http://www.apress.com/9781430234043">Pro ASP.NET MVC 3 Framework</a> by Adam Freeman and Steven Sanderson (Apress).</p> <p>What’s Wrong with ASP.NET Web Forms? <br />Traditional ASP.NET Web Forms development was a great idea, but reality proved more complicated. <br />Over time, the use of Web Forms in real-world projects highlighted some shortcomings: <br />•  View State weight: The actual mechanism for maintaining state across requests <br />(known as View State) results in large blocks of data being transferred between the <br />client and server. This data can reach hundreds of kilobytes in even modest web <br />applications, and it goes back and forth with every request, frustrating site visitors <br />with slower response times and increasing the bandwidth demands of the server. <br />•  Page life cycle: The mechanism for connecting client-side events with server-side <br />event handler code, part of the page life cycle, can be extraordinarily complicated <br />and delicate. Few developers have success manipulating the control hierarchy at <br />runtime without getting View State errors or finding that some event handlers <br />mysteriously fail to execute. <br />•  False sense of separation of concerns: ASP.NET’s code-behind model provides a <br />means to take application code out of its HTML markup and into a separate code- <br />behind class. This has been widely applauded for separating logic and <br />presentation, but in reality, developers are encouraged to mix presentation code <br />(for example, manipulating the server-side control tree) with their application <br />logic (for example, manipulating database data) in these same monstrous code- <br />behind classes. The end result can be fragile and unintelligible. <br />•  Limited control over HTML: Server controls render themselves as HTML, but not <br />necessarily the HTML you want. Prior to ASP.NET 4, the HTML output usually <br />failed to comply with web standards or make good use of Cascading Style Sheets <br />(CSS), and server controls generated unpredictable and complex ID values that are <br />hard to access using JavaScript. These problems are reduced in ASP.NET 4, but it <br />can still be tricky to get the HTML you expect. <br />•  Leaky abstraction: Web Forms tries to hide away HTML and HTTP wherever <br />possible. As you try to implement custom behaviors, you frequently fall out of the <br />abstraction, which forces you to reverse-engineer the postback event mechanism <br />or perform obtuse acts to make it generate the desired HTML. Plus, all this <br />abstraction can act as a frustrating barrier for competent web developers.  <br />•  Low testability: The designers of ASP.NET could not have anticipated that <br />automated testing would become an essential component of software <br />development. Not surprisingly, the tightly coupled architecture they designed is <br />unsuitable for unit testing. Integration testing can be a challenge, too. <br />ASP.NET has kept moving. Version 2.0 added a set of standard application components that can <br />reduce the amount of code you need to write yourself. The AJAX release in 2007 was Microsoft’s <br />response to the Web 2.0/AJAX frenzy of the day, supporting rich client-side interactivity while keeping <br />developers’ lives simple. The most recent release, ASP.NET 4, produces more predictable and standards- <br />compliant HTML markup, but many of the intrinsic limitations remain. </p> Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-4373945007829324222010-09-21T16:20:00.001-04:002010-10-28T12:25:10.944-04:00Old unresolved IE (pre 9) DOM bugs hinder its ability to work with HTML5<p> <br />I've just started to read "Introducing HTML5" book <a href="http://goo.gl/DDa9">http://goo.gl/DDa9</a> (my first HTML5 tutorial) and it's simply wonderful. I enjoy its concise but very live language a lot.</p> <p> <br />On a page 11 <a href="http://goo.gl/IAi3">http://goo.gl/IAi3</a> Bruce Lawson said, "The way to cajole IE into applying CSS to HTML5 is to use JavaScript. Why? This is an inscrutable secret, and if we told you we'd have to kill you. (Actually, we don't know.) If you add <br />the following JavaScript into the head of the page <br /> <br /><script> <br />document.createElement(‘header’); <br />document.createElement(‘nav’); <br />document.createElement(‘article’); <br />document.createElement(‘footer’); <br /></script> <br /> <br />IE will magically apply styles to those elements, provided that there is a <body> element in the markup" </p> <p>I think I know  - why. <br />Two years ago I found an article in a famous among .NET developers blog by Rick Strahl <a href="http://goo.gl/a4Cy">http://goo.gl/a4Cy</a> about a very unfortunate Internet Explorer feature: it automatically creates matching global JavaScript objects for all DOM elements on the page based on their IDs. This clutters global space and often leads to clashes with user-defined JavaScript objects, which often leads to "Object doesn’t support this property or method" errors being displayed. </p> <p>I bet these things are related: for IE to operate normally it needs all the DOM elements on the page to be in a global namespace. JavaScript snippet does just that - puts HTML5 'header', 'nav', etc. elements into a global namespace! </p> <p>I already blogged <a href="http://goo.gl/ducY">http://goo.gl/ducY</a> about this and another IE issue and tried desperately to notify IE staff... well, they don't like to be notified at all, they don't like bug reports.</p> <p>#twitter</p> <p><strong>An update of 10/19/2010</strong>: I got a nice message from Microsoft Connect Team saying that a bug was resolved in IE 9. They said, <font color="#004080">“</font><font color="#004080">This issue was resolved in Internet Explorer 9 Platform Preview Build 3 released on 6/23/2010… </font><font color="#004080"><strong><em>The fix prevents the error message. Note, IE still allows the DOM element to exist as a global javascript object.</em></strong> (Bold-italic mine, V.K.)</font><font color="#004080">”</font></p> <p><font color="#000000">Well, I’m not sure that keeping DOM elements in global JavaScript namespace is a good idea (other browsers don’t do it), but at least they found a workaround. It’s interesting to see how correctly it now supports HTML 5 and if document.createElement() trick described above is still necessary.</font></p> Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-10016964324838235472010-07-02T12:55:00.001-04:002010-10-19T13:02:25.873-04:00About Internet Explorer DOM bugs<p>Almost four year ago I wrote a post <a href="http://goo.gl/VKTc">http://goo.gl/VKTc</a> in my blog describing incorrect behavior of window.onblur event in IE and a workaround. At that time I tried hardly to submit a bug report to Microsoft, but couldn't find a way to do that. My blog isn't really that popular, but I received numerous thanks from web developers for posting a workaround. </p> <p>Two years ago I found an article in a famous among .NET developers blog by Rick Strahl <a href="http://goo.gl/a4Cy">http://goo.gl/a4Cy</a> about another very unfortunate Internet Explorer feature: it automatically creates matching global JavaScript objects for all DOM elements on the page based on their id. This clatters global space and often leads to clashes with user-defined JavaScript objects, which often leads to "Object doesn’t support this property or method" errors being displayed. </p> <p>Recently, thanks to Dimitri Glazkov's buzz about Enhanced Scripting in IE9 <a href="http://goo.gl/CO1v">http://goo.gl/CO1v</a> I asked the same questions on MSDN IE blog <a href="http://goo.gl/Un5g">http://goo.gl/Un5g</a> and got a suggestion to submit bug report to Microsoft Connect. </p> <p>Then I found that someone already submitted "Incorrect behavior of window.onblur event" bug to IE blog <a href="http://goo.gl/6HlF">http://goo.gl/6HlF</a>. Unfortunately it was marked as "Won't fix" by IE 9 team. So, are we looking for another four years before this bug will be fixed? I doubt Internet Explorer would survive that long. </p> <p>At least I went ahead and submitted "IE automatically creates matching global JavaScript objects for all DOM elements on the page based on their id" bug <a href="http://goo.gl/Eugd">http://goo.gl/Eugd</a> on Rick's behalf. Let's see if MS IE team would be willing to fix that.</p> <p>Want to <a href="http://goo.gl/pMxd" target="_blank">buzz</a> about it?</p> <p><strong>An update of 10/19/2010</strong>: I got a nice message from Microsoft Connect Team saying the following:</p> <p><font color="#004080">“Greetings from Microsoft Connect! <br />This notification was generated for feedback item: IE automatically creates matching global JavaScript objects for all DOM elements on the page based on their id. which you submitted at the Microsoft Connect site.</font></p> <p><font color="#004080">Thank you for your feedback. <br />This issue was resolved in Internet Explorer 9 Platform Preview Build 3 released on 6/23/2010. Please verify the change and file a new feedback (or reactivate the existing one) if the problem persists.</font></p> <p><font color="#004080"><strong><em>The fix prevents the error message. Note, IE still allows the DOM element to exist as a global javascript object.</em></strong> (Bold-italic mine, V.K.)</font></p> <p><font color="#004080">Best regards, <br />The Internet Explorer Team <br />Thank you for using Microsoft Connect!”</font></p> <p><font color="#000000">Well, I’m not sure that keeping DOM elements in global JavaScript namespace is a good idea (other browsers don’t do it), but at least they found a workaround. <br />It was a first time in my life MS directly communicated to me, that’s nice.</font></p> Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-41372621967303311422010-05-07T16:05:00.001-04:002010-05-07T16:09:27.404-04:00What Facebook’s recent bug tells us<p>I was listening to <a href="http://www.twit.tv/twig41" target="_blank">latest TWIG</a> when I heard that Facebook recently had a <a href="http://mashable.com/2010/05/05/facebook-chat-down/" target="_blank">security breach</a>. They explained that Facebook has a feature allowing to mimic a friend’s login for viewing on your profile by the eyes of that friend (“With Preview My Profile, users can view how their profile appears to any given Facebook friend”). And it happens that that friend’s login were almost real, allowing to see the live chats and friend requests of the friend in question.</p> <p>OK, security breaches happen. They are discovered and then fixed. But what this particular case tells us about Facebook platform? I suspect, it tells a lot of negative and alarming things. Let me explain.</p> <p>We have a similar feature in our Corporate Intranet written in a mix of classic ASP and ASP.NET. We call it Super User (SU) login. SU allows for selected administrators to login into Intranet as a different employee to debug some issues. In fact, SU login matches a regular login by 99%. One per cent of difference is that there is a special set of private user’s data which is visible only to user himself or to a user and strictly defined group of people, for example HR. In case an admin who uses SU is not in HR group, employee’s private data is not visible through SU login.</p> <p>A several years ago security breaches like one which happened to Facebook was pretty common for us too. But now we virtually eliminated their possibility. <br /> We use a regular ASP feature to store in memory current user’s identity – a Session variable. When SU login happens, user’s Session variable is actually reset to identity of user being SUed. It allows to fully mimic other user’s experience. In SU login, a second Session variable is set, keeping original user’s identity and indicating that we are in SU mode. When it comes to seeing some restricted private user’s data, code checks if user has permissions to see it and, if we are in SU mode, if actual user has rights to see it as well.</p> <p>A real question is how system determines permissions (rights) of a particular user. Normally, <strong>Rights</strong> are attached either to user himself, or to <strong>Roles</strong> that user share. Initially, our Intranet used a bunch of ‘If’ statements in ASP code. If a user is HR, this is allowed on this page. If a user is DBA, he can do this and this. If you have a developer experience, it should be absolutely clear to you that such a system is very fragile and inconsistent. To break it, It’s enough to add a new page and forget some ‘If’ statement, it’s enough to modify Rights of a particular Role and forget to modify ‘Ifs’ on one page. It even much easier to add a new page and forget that you need to check not only rights of a current user, but also, in case it’s a SU login, rights of original user. <br />So, a system described above is really amateurish, fragile, hard to maintain, and no-professional.</p> <p>Now you probably understand what I’m thinking about Facebook? As a web developer with 15 years of experience, I have a strong feeling, that Facebook, which had a bunch of developers of different levels, which grew up from a small system written in PHP for college students, suffers from the same inconsistent code, uses hard-coded ‘If’ statements to determine user’s rights and to mimic another user’s experience in “Preview My Profile”. This assumed amateurish inconsistent system in combination of its <a href="http://www.twit.tv/twig39" target="_blank">Facebook Über Alles</a> syndrome looks especially <a href="http://techlyric.blogspot.com/2010/04/clear-step-by-step-instruction-of-how.html" target="_blank">dangerous</a> and incapable of keeping users privacy.</p> <p>Finally, a system managing users permissions looks as a relational structure in its essence. Basically, there should be tRight table, tRole table, and tRightOfRole link table (many-to-many relationships). It’s a bit more complex if Rights are assignable not only to Roles, but to individual Users as well. It gets some additional complexity if Role-Right combinations are different for different pages or sections of your system (web site). We introduced a notion of <strong>Scope</strong>. Both Roles and Rights are defined either globally or on a particular Scope within a system. Role-Right combination is to be assigned on a Scope too. A resulting <strong>relational</strong> system is extremely powerful and flexible, much <a href="http://pro-thoughts.blogspot.com/search/label/SharePoint" target="_blank">more flexible</a> than any system written based on Active Directory groups, like <a href="http://pro-thoughts.blogspot.com/search/label/SharePoint" target="_blank">MS SharePoint</a> (We tried to use <a href="http://sharepoint.microsoft.com/" target="_blank">MOSS 2007</a> and found it not flexible enough to accommodate for business rules). <br /> And yes, we actually wrote such a relational system, called Roles Rights Management (RRM). Besides relational structure I described above, it uses some clever techniques and <a href="http://www.devx.com/dotnet/Article/6962/0/page/4" target="_blank">HttpModules</a>, which allowed us to automate its usage. It is not a responsibility of particular programmer anymore, to properly check user’s permissions to allow/disallow viewing a page or to filter data. In most case, <a href="http://www.google.com/search?hl=en&rls=com.microsoft%3Aen-us%3AIE-SearchBox&rlz=1I7SKPB_en-US&q=security+trimming&aq=1&aqi=g10&aql=&oq=security+tri&gs_rfai=" target="_blank">Security Trimming</a> happens automatically. <br />That’s what I think Facebook programmers failed to implement.</p> Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-7747141084499493662010-03-18T16:57:00.005-04:002010-05-06T17:26:29.241-04:00More Details on Microsoft's plans to ruin jQuery<em><a href="http://visualstudiomagazine.com/articles/2010/03/18/walther-on-asp.net.aspx?sc_lang=en">Visual Studio Magazine</a>: "Microsoft is working in a number of directions, including databinding, the script loader and contributing to development of templating functionality as part of the jQuery core."</em> <br />
Oh, no Microsoft! Please, please don't ruin jQuery! Don't make it as insanely overcomplicated as your own AJAX.NET. Don't mix together JavaScript client code with server-side "loaders". Don't you understand that RESTless WEB client is not the same as .NET server or Win desktop?!Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-14867442755343505402010-02-23T12:15:00.001-05:002010-02-23T12:39:44.636-05:00Squeryl — Introduction<a href="http://max-l.github.com/Squeryl/index.html">Squeryl — Introduction</a><br /><br /><i>"Squeryl is a strongly typed DSL (domain specific language) for SQL databases in which table rows are manipulated as Scala objects via an SQL like language"</i><br /><br />I hate the idea. Aren't we already fed up with MS datasets which break n-Tier application structure by bringing excessive and over-complicated database only related properties into a domain layer?<br />To me it is clear, that there is only three legitimate ways of creating decoupled n-Tier applications:<br />1) Use hand-made Data Access Layer objects;<br />2) Use ORM tools like [N]Hibernate;<br />3) Use object-oriented databases like db4oВладимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-65278904905234612812010-01-27T14:46:00.001-05:002012-12-15T00:03:22.078-05:00‘The WebForms Rant’ by karl Seguin<p> <br />"ASP.NET WebForms is an ugly and messy framework that complicates an otherwise simple thing. ViewState, codebehind, postback, page lifecycle and databinding are things that you have to constantly program against." <br />"A framework that accepts that HTTP is stateless will always be simpler, cleaner and more powerful that a framework that doesn't." </p> <p>Wow! <strong><a title="‘The WebForms Rant’ by karl Seguin" href="http://codebetter.com/blogs/karlseguin/archive/2010/01/22/the-webforms-rant.aspx" target="_blank">Well done</a></strong> :) <br />I agree completely. Karl probably is a first developer whom I highly respect (as my virtual teacher too) and who is stating the matter straight and without usual 'polites'. </p> <p>One more important argument against WebForms is that it leads to hard-to-avoid "Web page was expired" problem due to inability to implement Post-Redirect-Get (PRG) pattern. <br />See <a href="http://pro-thoughts.blogspot.com/2009/06/classic-aspnet-improper-abstractions.html">http://pro-thoughts.blogspot.com/2009/06/classic-aspnet-improper-abstractions.html</a> <br /> <br />I also really like a classic <a href="http://wekeroad.com/2009/04/22/i-spose-ill-just-say-it-you-should-learn-mvc" target="_blank">I Spose I’ll Just Say It: You Should Learn MVC</a> article by Rob Conrey. <br />Finally, recent <a href="http://codebetter.com/blogs/ian_cooper/archive/2010/01/27/mvc-or-webforms.aspx" target="_blank">MVC or WebForms: It's more about client side vs server side</a> article by Ian Cooper is good too. <br /> <br />Don’t forget to read comments under all those articles!</p> Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-64865887687030009212009-12-17T02:16:00.001-05:002009-12-17T02:19:00.663-05:00My new Android blogI decided to start a separate blog fully dedicated to Android usage and development. You're very welcome to visit <a href="http://webofandroids.blogspot.com/">Wonderful Android: Using and Developing</a>.Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-35344825224339801022009-11-03T02:02:00.001-05:002009-11-03T02:02:44.856-05:00How to install missing LaserJet 4MPlus driver on Windows 7<p> </p> <p>I found on HP forum site <a href="http://h30434.www3.hp.com/psg/board/message?board.id=win7Beta&message.id=3193#M3193">the following advice</a>:</p> <p><em>The Laserjet 4M drivers (and many others)  are actually available through the Windows Update process.  Try the following:  go to the Printers folder, select Add a Printer, select the appropriate port, then when the "Chose a Printer Model" dialog comes up select "Windows Update".</em> </p> <p>Unfortunately, there was one strange Windows feature or probably a bug... as it always happens with Windows. A first bug I discovered in Windows 7, which is actually much better than its predecessors.</p> <p>When I tried to installed my LaserJet 4MPlus network printer on Win 7 64 bit by clicking Add Printer, as you described above, there was <strong>NO Windows Update button visible</strong>. Finally, I selected an incorrect printer model and installed that printer driver. After doing it, I right-clicked on a printer, chose Printer Properties => Advanced => New Driver and ... what a miracle: Windows Update button suddenly appeared!</p> <p>If you ask me how did I find this way, I would answer: a long practice working with a buggy Windows software.</p> Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-41254173008735942262009-06-02T14:38:00.001-04:002009-06-02T17:32:15.541-04:00Classic ASP.NET: improper abstractions and ruined REST<p><a title="http://herdingcode.com/?p=183" href="http://herdingcode.com/?p=183">http://herdingcode.com/?p=183</a></p> <p>1. No one ever anywhere answered the simple question: how to avoid POST operations in a classic ASP.NET when GET operations should be used instead according to a common sense and REST. <br />POST - for changing data, GET - for reading. No one found any decent way to avoid "Web page was expired"  messages resulting from improper usage of POST. No way to <a href="http://www.strong-point.com/Blogs/tabid/87/EntryID/9/Default.aspx">PRG</a>.</p> <p>To me, this fact alone makes “classic” ASP.NET’s Web Forms approach inappropriate.</p> <p>2. Yes you can find a workaround for anything, but you’re ending up battling against a framework rather than using it most of the time. And maybe even worse: you’re battling against MS tutorials and books which teach you that ASP.NET-in-24-hours-dataset-no-custom-code-monolithic development.</p> <p>3. It’s pretty obvious to me, that event-driven model moved from Windows desktop development to Web does not correspond to Request/Response nature of Web and makes programming much more complicated, than even with a plain old ASP. I’d be pretty happy to have lain ASP + C# 3.5 + Intellisense, and believe me, my code would be at the same time more user-friendly and better structured than monstrous code-behind of those ugly master/detail ASP.NET pages.</p> <p>4. I have nothing against Http Modules, Handlers, etc. They are powerful tools. <br /> But I personally hate Web Forms so much, I think that all those words about Web Forms better in one situations and MVC in another is just a precaution: people understand that MVC is better but are afraid to talk.</p> <p>Finally, <strong>everything is already said</strong> in <a href="http://blog.wekeroad.com/blog/i-spose-ill-just-say-it-you-should-learn-mvc/">this article</a> and all the comments below.</p> Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-11550322120667902912009-06-01T21:18:00.001-04:002009-06-01T21:18:01.926-04:00“Mega” menu? Is it like almost unusable Office 2007 menu?<p><a href="http://www.sitepoint.com/blogs/2009/03/31/make-a-mega-drop-down-menu-with-jquery/">Usability guru Jakob Nielsen thinks that “mega” menus are good</a>. But is it something similar to Office 2007’s “ribbon” menu?</p> <p>Office 2007 menu is awful. It's a major step back from a standard and simple Office 2003 menu. Really hard to find what you need, you never sure which main menu bar link to click. My daughter told me to uninstall Office 2007 from her machine because she cannot find anything. If "mega" menu is something like that, I strongly disagree with Jakob Nielsen. The less pictures and other unnecessary graphical elements are in a menu - the better it is.</p> Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-25838664490717481422009-05-06T10:18:00.000-04:002009-05-06T10:20:25.441-04:00Rob Conery: I Suppose I’ll Just Say It: You Should Learn MVC<a href="http://blog.wekeroad.com/blog/i-spose-ill-just-say-it-you-should-learn-mvc/">http://blog.wekeroad.com/blog/i-spose-ill-just-say-it-you-should-learn-mvc/</a><br /><br />Comments under this article are as interesting as article itself.<br />I only hope I’ll be allowed to write my next ASP.NET project in ASP.NET MVC. I already bought Rob’s book.Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-17314759229947813632009-02-11T08:57:00.001-05:002009-02-11T09:04:18.155-05:00Write deep Clone(). Forget about ICloneable.I was chatting with my co-worker about implementing Clone() method for our hierarchy of classes. It's not easy to implement interfaces (think about ICloneable) for class hierarchies. Some tips might be found in <a href="http://en.csharp-online.net/CSharp_Coding_Solutions%E2%80%94Implementing_Interfaces" rel="nofollow">Implementing Interfaces at C# Online.NET</a> article, in <a href="http://blog.reamped.net/post/2008/03/Implementing-Interfaces-ICloneable-and-IComparable.aspx" rel="nofollow">Implementing Interfaces: ICloneable and IComparable</a> article, and in <a href="http://bytes.com/groups/net-c/270952-advantages-icloneable" rel="nofollow">Advantages of ICloneable?</a> discussion.<br />As Zach said, it's easier just to implement a virtual Clone() method in a base class and to override it in derived classes as necessary.<br /><br />I started to look for information about ICloneable and found the following quite unequivocal guidelines:<br /><br /><span style="color: darkblue;">Caution. Avoid implementing ICloneable. As alarming as that sounds, Microsoft is actually making this recommendation. The problem stems from the fact that the contract doesn’t specify whether the copy should be deep or shallow. In fact, as noted in Krzysztof Cwalina and Brad Abrams’ Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries (Boston, MA: Addison-Wesley Professional, 2005), Cwalina searched the entire code base of the .NET Framework and couldn’t find any code that uses ICloneable. Had the Framework designers and developers been using this interface, they probably would have stumbled across the omission in the ICloneable specification and fixed it.<br />However, this recommendation is not to say that you shouldn’t implement a Clone method if you need one. If your class needs a clone method, you can still implement one on the public contract of the class without actually implementing ICloneable.</span><br /><a href="http://www.amazon.com/Accelerated-C-2008-Trey-Nash/dp/1590598733/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1234359739&sr=8-1" rel="nofollow">Accelerated C# 2008</a><br /><br /><span style="color: blue;">Because the contract of ICloneable does not specify the type of clone implementation required to satisfy the contract, different classes have different implementations of the interface. Consumers cannot rely on ICloneable to let them know whether an object is deep-copied or not. Therefore, we recommend that ICloneable not be implemented.<br />The moral of the story is that you should never ship an interface if you don't have both implementations and consumers of the interface. In the case of ICloneable, we did not have consumers when we shipped it. I searched the Framework sources and could not find even one place where we take ICloneable as a parameter.<br /><b>x</b> DO NOT implement ICloneable.<br /><b>x</b> DO NOT use ICloneable in public APIs.<br /><b>x</b> CONSIDER defining the Clone method on types that need a cloning mechanism. Ensure that the documentation clearly states whether it is a deep- or shallow-copy.</span><br /><a href="http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development/dp/0321545613/ref=sr_1_1?ie=UTF8&qid=1234360065&sr=1-1" rel="nofollow">Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries</a>Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-80521609158627857412008-12-30T08:48:00.013-05:002009-03-19T13:26:54.299-04:00Call a method only if a supplied argument is not NullSuppose you have a C# method which only works correctly if its parameter value is not Null, otherwise it either throws an exception or returns wrong value. Sometimes you cannot guarantee that a parameter value is not Null, because it was passed from outside, was read from DB, etc. Instead of writing your custom code again and again, which checks a parameter value and only calls a method if it is not Null, it may be more convenient to re-use a common helper method. Overloaded CallIfArgumentNotNull() methods shown below are such helpers. I was somehow inspired by reading <a href="http://msmvps.com/blogs/jon_skeet/archive/2008/06/20/automatic-lambda-expressions.aspx">this article</a> by Jon Skeet (lazy evaluation) .<br /><br /><div style="background: white none repeat scroll 0% 0%; -moz-background-inline-policy: -moz-initial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial;font-size:10pt;color:black;"><pre style="margin: 0px;"> <span style="color:green;">// If a first argument of type int? is not Null, a supplied method (second argument)</span></pre><pre style="margin: 0px;"> <span style="color:green;">// is called with a first argument passed in and its return value is returned.</span></pre><pre style="margin: 0px;"> <span style="color:green;">// If a first argument is Null, a default(T) is returned</span></pre><pre style="margin: 0px;"> <span style="color:green;">// (null for reference types, 0 from Integer, etc.)</span></pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">static</span> T CallIfArgumentNotNull<T>(<span style="color:blue;">int</span>? arg, <span style="color: rgb(43, 145, 175);">Func</span><<span style="color:blue;">int</span>, T> func) {</pre><pre style="margin: 0px;"> <span style="color:blue;">return</span> (arg != <span style="color:blue;">null</span>) ? func((<span style="color:blue;">int</span>)arg) : <span style="color:blue;">default</span>(T);</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:green;">// If a first argument of type int? is not Null, a supplied method (second argument)</span></pre><pre style="margin: 0px;"> <span style="color:green;">// is called with a first argument passed in and its return value is returned.</span></pre><pre style="margin: 0px;"> <span style="color:green;">// If a first argument is Null, a third argument value is returned.</span></pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">static</span> T CallIfArgumentNotNull<T>(<span style="color:blue;">int</span>? arg, <span style="color: rgb(43, 145, 175);">Func</span><<span style="color:blue;">int</span>, T> func, T defResult) {</pre><pre style="margin: 0px;"> <span style="color:blue;">return</span> (arg != <span style="color:blue;">null</span>) ? func((<span style="color:blue;">int</span>)arg) : defResult;</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:green;">// If a first argument of type A? is not Null, a supplied method (second argument)</span></pre><pre style="margin: 0px;"> <span style="color:green;">// is called with a first argument passed in and its return value is returned.</span></pre><pre style="margin: 0px;"> <span style="color:green;">// If a first argument is null, a third argument value is returned.</span></pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">static</span> T CallIfArgumentNotNull<A, T>(<span style="color: rgb(43, 145, 175);">Nullable</span><A> arg, <span style="color: rgb(43, 145, 175);">Func</span><A, T> func, T defResult)</pre><pre style="margin: 0px;"> <span style="color:blue;">where</span> A : <span style="color:blue;">struct</span> {</pre><pre style="margin: 0px;"> <span style="color:blue;">return</span> (arg != <span style="color:blue;">null</span>) ? func((A)(arg)) : defResult;</pre><pre style="margin: 0px;"> }</pre></div>Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-24363852953326558552008-11-20T08:29:00.000-05:002008-11-20T08:30:52.429-05:00An easy way to override Chrome bookmarksIt is quite easy to manually override Chrome “Other Bookmarks” with your Firefox bookmarks:<br />1) In Chrome, click on “Other Bookmarks” and, if you have any, right click on each bookmark and delete it.<br />2) Use “Import Bookmarks and Settings”, switch to import from Firefox, clear all checkboxes except ‘Bookmarks’ one and hit ‘Import’.<br />3) This will keep all imported bookmarks in one ‘folder’, which is actually good, because next time when you decide to override Chrome bookmarks, you will need to delete only one Other Bookamrks ‘folder’ by right-clicking on it.<br /><br />(On WinXP machine Chrome keeps bookamrks in C:\Documents and Settings\-your-name-\Local Settings\Application Data\Google\Chrome\User Data\Default\Bookmarks file. This is a text file which looks similar to XML. )Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com1tag:blogger.com,1999:blog-17567386.post-90434304998833242792008-11-13T16:04:00.001-05:002008-11-13T16:20:13.638-05:00Configuring MS DTC on WinXP, Server 2003, and Server 2008 machines<div>Our N-Tier ASP.NET (C# 2008 / SQL Server) application uses MS DTC transactions for database integrity. This allows a transaction to embrace several BL or DL method calls without sharing the same database connection.</div><div>A usage is simple:</div><div><br /></div><div>using System.Transactions; </div><div><br /></div><div>using (TransactionScope myTransactionScope = new TransactionScope()) {</div><div> // Do any database related work you need: call methods, open and close connections, update multiple tables.</div><div> // Database integrity is preserved even if one of methods which update database fails.</div><div><br /></div><div> myTransactionScope.Complete();</div><div>}</div><div><br /></div><div>To support MS DTC all servers which run our application (including developers' machines) and servers which host a databases were properly configured. (Configuring developers' machines allowed to work properly with your local copy of application and with a remote database.</div><div><br /></div><div>1) To configure DTC on Windows XP, Windows Server 2003 machine follow <a href="http://support.microsoft.com/kb/899191/">these instructions</a> to open Component Services window and configure DTC.</div><div>Make sure that "Use local coordinator" check box is checked on MSDTC tab of computer properties window.</div><div>Make sure that "Network DTC access" is checked on MSDTC=>Security Configuration window, that both "Allow Inbound" and "Allow Outbound" are checked, and DTC Logon Account is set to "NT AUTHORITY\NetworkService".</div><div>2) On Windows Server 2008 machine it's pretty much the same, except that in Component Services window has My Computer -> Distributed Transaction Coordinator -> Local DTC node, on which you'll need to right-click and choose Properties.</div><div>3) After configuring DTC restart your machine.</div><div>4) Open Control Panel -> Administrative Tools -> Services and make sure that DTC is set to start automatically and is started.</div><div><br /></div><div><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFC1kKF2bwzE_kPMMenKiBUROnX4NYJAdgz7sGToOvn4znd_ObxgAc42ZXM-qBGZqb1gJByGCemcq4Q-LjZitGQ_-RcJwFg2c9_vwCBTepfJX3dyXYfId3mKM7Jd5H36u1WAyJDg/s1600-h/EnablingDTC.png"><img style="cursor:pointer; cursor:hand;width: 400px; height: 394px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFC1kKF2bwzE_kPMMenKiBUROnX4NYJAdgz7sGToOvn4znd_ObxgAc42ZXM-qBGZqb1gJByGCemcq4Q-LjZitGQ_-RcJwFg2c9_vwCBTepfJX3dyXYfId3mKM7Jd5H36u1WAyJDg/s400/EnablingDTC.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5268254479716452290" /></a><br /></div><div><br /></div><div>Reference on using DTC with N-Tier application: <a href="http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=419">http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=419</a></div><div><br /></div>Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com1tag:blogger.com,1999:blog-17567386.post-20343040394418593252008-11-02T23:11:00.000-05:002008-11-02T23:21:14.890-05:00The best of F# and C# -- Nemerle? Scala? various approaches to mixed OOP - functional languages<span class="Apple-style-span" style="font-family: Arial; font-size: 13px; ">Today I was pointed out to yet another mixed OOP and functional language: Nemerle. I looked at the <a href="http://nemerle.org/Features">Nemerle features</a> and immediately spotted something very familiar, "<i>Probably the most important feature of Nemerle is the ability to mix object oriented and functional programming styles. The top-level program structure is object oriented, while in the body of methods one can (but is not forced to) use functional style. In some programming problems this is very handy.</i>" It sounds exactly the same as what is stated about <a href="http://www.scala-lang.org/">Scala programming language</a>, "<i>Scala is a general purpose programming language designed to express common programming patterns in a concise, elegant, and type-safe way. It smoothly integrates features of object-oriented and functional languages.</i>" A main platform for Scala is JVM, but it's CLR variant already exists and is planned to be fully developed.<br /><br />I think that both C# and Java in their pursuit of simplicity dropped too many functional features which existed in their common parent - C++. I've just <a href="http://pro-thoughts.blogspot.com/2008/11/learning-languages-in-comparison-how.html">blogged about it</a> today. So, both communities felt the need for more functional OOP languages. It looks like that both Scala and Nemerle chose the same approach which creators of Java used: to build up on the base of familiar and wide-spread language in a hope that it gives an immediate advantage of huge number of programmers who are familiar with the syntax and want to try new language. I don't know about Nemerle yet and I still know too little about F#, but Scala language found a very natural and consistent way of combining object oriented and functional features and is even better OOP language than Java.<br /><br />I think people are absolutely right, when they are saying, that it's hard to catch up with F#, "because the syntax of the ML - derivative languages is just too foreign for those with only imperative language experience". I felt it by myself when I was trying to start learning language using "<a href="http://www.amazon.com/Expert-F-Experts-Voice-Net/dp/1590598504">Expert F#</a>" book, having no prior ML experience.<br />But there is a flip side: now, when - thanks to an excellent "<a href="http://www.manning.com/petricek">Real World Functional Programming</a>" book by Tomas <span class="Apple-style-span" style="font-size: 12px; ">Petricek</span> I started to understand both functional concepts and beauty of ML syntax, I feel that more graduate approach taken by Scala (and probably - Nemerle) may in fact postpone real understanding of a functional nature of new languages. It's possible to program in Scala as in "improved Java" and never learn its functional features. And thanks to more steep approach of F# I now better understand and try to pursue functional approach in Scala and better understand ideas behind LINQ...</span>Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com3tag:blogger.com,1999:blog-17567386.post-33649789339923528822008-11-02T18:29:00.002-05:002008-11-30T17:55:08.486-05:00Learning languages in comparison. How Scala re-introduces what was dropped in C++ to create Java.<div><span class="Apple-style-span" style="font-weight: bold;"><span class="Apple-style-span" style="font-style: italic;">An update (30/11/2008)</span></span>: I realize that a title of this post sounds silly. I never tried to say something like "Scala has C++ roots" or so. Scala is "an attempt to come up with a decent statically typed language that is both functional and object-oriented and that interoperates on standard VMs" (Martin Odersky in a <a href="http://www.codecommit.com/blog/scala/is-scala-not-functional-enough">comment here</a>). My point is: too much (including some functional features) was dropped when C++ was "simplified" by Java creators. </div><div><br /></div><div>Scala allows to pass variable length argument list to a function defined like</div><div><br /></div><div>def echo(args: String*) =</div><div> for (arg <- args) println(arg)</div><div><br /></div><div>In "<a href="http://www.artima.com/shop/programming_in_scala">Programming in Scala</a>" authors says that,</div><div>'... Thus, the type of args inside the echo function, which is declared as type "String*" is actually Array[String]'</div><div><br /></div><div>It immediatelly reminds me C++, which uses similar syntax of passing array arguments. I'm pretty sure Martin Odersky chose asterisk, because it is used in C/C++, although in C/C++ it allows to pass array parameters, not a variable length argument list, and denotes a pointer to a first element of array.</div><div><br /></div><div>There is definitely a feel, that C++ is more functional language than Java, for example a name of a function is a pointer (reference) variable pointing to a function itself, which allows to pass a function to another function as parameter and return as return value. First-class functions, isn't it?</div><div>So, Scala feels partly as a consistent attempt to re-introduce to Java functional features which were dropped when Java creators used C++ to produce new [over?]simplified language.</div><div><br /></div><div>Personally, I always loved when authors of books described new languages in comparison to existing ones, like Trey Nash is doing in his "<a href="http://www.amazon.com/Accelerated-C-2008-Trey-Nash/dp/1590598733/">Accelerated C# 2008</a>", comparing C# to C++, like David Flanagan is doing in "<a href="http://www.amazon.com/JavaScript-Definitive-Guide-David-Flanagan/dp/0596101996/">JavaScript. The Definite Guide</a>", comparing JavaScript to C/C++, and like Bruce Eckel is doing in "<a href="http://www.amazon.com/Thinking-Java-4th-Bruce-Eckel/dp/0131872486/">Thinking in Java</a>", comparing it to... C++ again. (By the way, Bruce is <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=221903">considering Scala</a> as a next "big" language, which will gradually and partially replace Java the same way Java did to C++.) One fresh and excellent example is "<a href="http://www.manning.com/petricek">Real World Functional programming in .NET</a>" by Tomas Petricek. This book introduces F# language (a merge of OCaml and .NET platform) and functional concepts in constant comparison to limited functional features of C# 3.0. It helps a lot to understand both F# and functional features of C#. It even helps to understand Scala, because functional concepts are the same in both F# and Scala.</div><div>To learn programming languages in comparison is not an easy task. But it is, in my opinion, a most powerful way to obtain real understanding of languages. Footnotes or special text blocks, describing similarities and diffrence between languages make a programming book shine.</div>Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com13tag:blogger.com,1999:blog-17567386.post-49762463490247162002008-09-12T14:39:00.005-04:002008-09-12T16:10:15.759-04:00How to decoratively set an attribute of a server-side control to some public property/value?Have you ever tried to decoratively set an attribute of a server-side control to some public property/value defined in code-behind code (or in a Business Layer)? Here's a simple example:<br /><br /><fieldset title="code"><!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green238\blue98;\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red255\green0\blue0;}??\fs20 \cb2\highlight2 <%\cf3\cb0\highlight0 @\cf0 \cf5 Page\cf0 \cf6 Language\cf3 ="C#"\cf0 \cf6 AutoEventWireup\cf3 ="true"\cf0 \cf6 CodeFile\cf3 ="TestPage.aspx.cs"\par ??\cf0 \cf6 Inherits\cf3 ="TestPage"\cf0 \cb2\highlight2 %>\par ??\par ??\cf3\cb0\highlight0 <!\cf5 DOCTYPE\cf0 \cf6 html\cf0 \cf6 PUBLIC\cf0 \cf3 "-//W3C//DTD XHTML 1.0 Transitional//EN"\par ??\cf0 \cf3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\par ??\par ??<\cf5 html\cf0 \cf6 xmlns\cf3 ="http://www.w3.org/1999/xhtml">\par ??<\cf5 head\cf0 \cf6 runat\cf3 ="server">\par ??\cf0 \cf3 <\cf5 title\cf3 >\cf0 Untitled Page\cf3 </\cf5 title\cf3 >\par ??</\cf5 head\cf3 >\par ??<\cf5 body\cf3 >\par ??\cf0 \cf3 <\cf5 form\cf0 \cf6 id\cf3 ="form1"\cf0 \cf6 runat\cf3 ="server">\par ??\cf0 \cf3 <\cf5 div\cf3 >\par ??\cf0 \cf3 <\cf5 asp\cf3 :\cf5 TextBox\cf0 \cf6 ID\cf3 ="TextBox1"\cf0 \cf6 runat\cf3 ="server"\cf0 \cf6 Text\cf3 ="\cf0\cb2\highlight2 <%\cb0\highlight0 =Eval(hitest) \cb2\highlight2 %>\cf3\cb0\highlight0 "\cf0 \cf3 />\par ??\cf0 \cf3 </\cf5 div\cf3 >\par ??\cf0 \cf3 </\cf5 form\cf3 >\par ??</\cf5 body\cf3 >\par ??</\cf5 html\cf3 >\par ??} --><br /><div style="background: white none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Courier New;font-size:10pt;color:black;"><pre style="margin: 0px;"><span style="background: rgb(255, 238, 98) none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><%</span><span style="color:blue;">@</span> <span style="color: rgb(163, 21, 21);">Page</span> <span style="color:red;">Language</span><span style="color:blue;">="C#"</span> <span style="color:red;">AutoEventWireup</span><span style="color:blue;">="true"</span> <span style="color:red;">CodeFile</span><span style="color:blue;">="TestPage.aspx.cs"</span></pre><pre style="margin: 0px;"> <span style="color:red;">Inherits</span><span style="color:blue;">="TestPage"</span> <span style="background: rgb(255, 238, 98) none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">%></span></pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"><span style="color:blue;"><!</span><span style="color: rgb(163, 21, 21);">DOCTYPE</span> <span style="color:red;">html</span> <span style="color:red;">PUBLIC</span> <span style="color:blue;">"-//W3C//DTD XHTML 1.0 Transitional//EN"</span></pre><pre style="margin: 0px;"> <span style="color:blue;">"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></span></pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"><span style="color:blue;"><</span><span style="color: rgb(163, 21, 21);">html</span> <span style="color:red;">xmlns</span><span style="color:blue;">="http://www.w3.org/1999/xhtml"></span></pre><pre style="margin: 0px;"><span style="color:blue;"><</span><span style="color: rgb(163, 21, 21);">head</span> <span style="color:red;">runat</span><span style="color:blue;">="server"></span></pre><pre style="margin: 0px;"> <span style="color:blue;"><</span><span style="color: rgb(163, 21, 21);">title</span><span style="color:blue;">></span>Untitled Page<span style="color:blue;"></</span><span style="color: rgb(163, 21, 21);">title</span><span style="color:blue;">></span></pre><pre style="margin: 0px;"><span style="color:blue;"></</span><span style="color: rgb(163, 21, 21);">head</span><span style="color:blue;">></span></pre><pre style="margin: 0px;"><span style="color:blue;"><</span><span style="color: rgb(163, 21, 21);">body</span><span style="color:blue;">></span></pre><pre style="margin: 0px;"> <span style="color:blue;"><</span><span style="color: rgb(163, 21, 21);">form</span> <span style="color:red;">id</span><span style="color:blue;">="form1"</span> <span style="color:red;">runat</span><span style="color:blue;">="server"></span></pre><pre style="margin: 0px;"> <span style="color:blue;"><</span><span style="color: rgb(163, 21, 21);">div</span><span style="color:blue;">></span></pre><pre style="margin: 0px;"> <span style="color:blue;"><</span><span style="color: rgb(163, 21, 21);">asp</span><span style="color:blue;">:</span><span style="color: rgb(163, 21, 21);">TextBox</span> <span style="color:red;">ID</span><span style="color:blue;">="TextBox1"</span> <span style="color:red;">runat</span><span style="color:blue;">="server"</span> <span style="color:red;">Text</span><span style="color:blue;">="</span><span style="background: rgb(255, 238, 98) none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><%</span>=hitest <span style="background: rgb(255, 238, 98) none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">%></span><span style="color:blue;">"</span> <span style="color:blue;">/></span></pre><pre style="margin: 0px;"> <span style="color:blue;"></</span><span style="color: rgb(163, 21, 21);">div</span><span style="color:blue;">></span></pre><pre style="margin: 0px;"> <span style="color:blue;"></</span><span style="color: rgb(163, 21, 21);">form</span><span style="color:blue;">></span></pre><pre style="margin: 0px;"><span style="color:blue;"></</span><span style="color: rgb(163, 21, 21);">body</span><span style="color:blue;">></span></pre><pre style="margin: 0px;"><span style="color:blue;"></</span><span style="color: rgb(163, 21, 21);">html</span><span style="color:blue;">></span></pre></div></fieldset><br />And in a code-behind file:<br /><br /><fieldset title="code"><!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf1 public\cf0 \cf1 partial\cf0 \cf1 class\cf0 \cf4 TestPage\cf0 : System.Web.UI.\cf4 Page\cf0 \{\par ??\par ?? \cf1 public\cf0 \cf1 string\cf0 hitest = \cf5 "Hello"\cf0 ;\par ??} --> <div style="background: white none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Courier New;font-size:10pt;color:black;"><pre style="margin: 0px;"><span style="color:blue;">public</span> <span style="color:blue;">partial</span> <span style="color:blue;">class</span> <span style="color: rgb(43, 145, 175);">TestPage</span> : System.Web.UI.<span style="color: rgb(43, 145, 175);">Page</span> {</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">string</span> hitest = <span style="color: rgb(163, 21, 21);">"Hello"</span>;</pre></div></fieldset><br />This example doesn't work, ASP.NET engine does not process <span style="font-style: italic;">hitest</span> and displays a text box with <%=hitest %> inside.<br /><br />I know, I'm doing something stupid and show everybody that I understand nothing about ASP.NET, but here's a reasoning behind my attempts:<br />In our application we use AjaxControlToolkit, and in particular - <a href="http://www.asp.net/AJAX/AjaxControlToolkit/Samples/MaskedEdit/MaskedEdit.aspx">MaskedEditExtender</a>. There is a complicated WebForm with a ListView and numerous text boxes for entering phones, there were millions of MaskEditExtenders with identical masks set to <!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red163\green21\blue21;\red255\green255\blue255;}??\fs20 \cf1 @"(9\{3\}) 9\{3\}-9\{4\}"} --><span style="color: rgb(163, 21, 21);">@"(9{3}) 9{3}-9{4}"</span>. (The same story for emails.) I don't like clattering a code with "magic" strings and numbers, so I decided to declare constants and toplace them into our common class sitting in App_Code:<br /><fieldset title="code"><!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red0\green128\blue0;\red163\green21\blue21;}??\fs20 \cf1 namespace\cf0 CoTs.Partners.Common \{\par ?? \cf1 public\cf0 \cf1 static\cf0 \cf1 class\cf0 \cf4 Util\cf0 \{\par ??\par ?? \cf5 // Use it to provide locks for thread safety\par ??\cf0 \cf1 public\cf0 \cf1 static\cf0 \cf1 object\cf0 SessionLock = \cf1 new\cf0 \cf1 object\cf0 ();\par ?? \par ?? \cf1 public\cf0 \cf1 const\cf0 \cf1 string\cf0 URLRegEx =\par ?? \cf6 @"(http|https|HTTP|HTTPS|Http|Https|HTtp|HTtps|HTTp|HTTps|HTTPs|hTtp|hTtps|\par ?? hTTp|hTTps|hTTP|hTTPs|hTTPS|htTp|htTps|htTP|htTPs|htTPS|\par ?? httP|httPs|httPS|httpS|HtTp|HttP|HtTps|HttPs|HttPS|\par ?? HtTpS|hTtPs|HttpS|HtTP|htTpS|hTTpS|HTTpS|hTTp)://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?"\cf0 ;\par ?? \cf1 public\cf0 \cf1 const\cf0 \cf1 string\cf0 MailRegEx = \cf6 @"\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*"\cf0 ;\par ?? \cf1 public\cf0 \cf1 const\cf0 \cf1 string\cf0 PhoneMask = \cf6 @"(9\{3\}) 9\{3\}-9\{4\}"\cf0 ;\par ??} --><br /><div style="background: white none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Courier New;font-size:10pt;color:black;"><pre style="margin: 0px;"><span style="color:blue;">namespace</span> CoTs.Partners.Common {</pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:blue;">class</span> <span style="color: rgb(43, 145, 175);">Util</span> {</pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">const</span> <span style="color:blue;">string</span> MailRegEx = <span style="color: rgb(163, 21, 21);">@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"</span>;</pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">const</span> <span style="color:blue;">string</span> PhoneMask = <span style="color: rgb(163, 21, 21);">@"(9{3}) 9{3}-9{4}"</span>;</pre></div></fieldset>Then, I thought, I would set <!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red0\green0\blue0;\red255\green0\blue0;\red255\green238\blue98;}??\fs20 \cf1 <\cf3 cc1\cf1 :\cf3 MaskedEditExtender\cf0 \cf5 ID\cf1 ="Phone2MaskedEditExtender1"\cf0 \cf5 InputDirection\cf1 ="LeftToRight"\cf0 \cf5 ClearMaskOnLostFocus\cf1 ="false"\cf0 \cf5 TargetControlID\cf1 ="Phone2TextBox"\cf0 \cf5 runat\cf1 ="server"\cf0 \cf5 Mask\cf1 ="\cf0\cb6\highlight6 <%\cb0\highlight0 #CoTs.Partners.Common.Util.PhoneMask \cb6\highlight6 %>\cf1\cb0\highlight0 "} --><br /><div style="background: white none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Courier New;font-size:10pt;color:black;"><pre style="margin: 0px;"><span style="color:blue;"><</span><span style="color: rgb(163, 21, 21);">cc1</span><span style="color:blue;">:</span><span style="color: rgb(163, 21, 21);">MaskedEditExtender</span> <span style="color:red;">Mask</span><span style="color:blue;">="</span><span style="background: rgb(255, 238, 98) none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><%</span>#CoTs.Partners.Common.Util.PhoneMask <span style="background: rgb(255, 238, 98) none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">%></span><span style="color:blue;">"</span></pre></div> - and voila. For some reason it worked fine for a ListView's "Edit", but bombed with an empty Mask in "Add". I started to investigate and decided that using of <span style="background: rgb(255, 238, 98) none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><%</span># is probably incorrect, because<span style="background: rgb(255, 238, 98) none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span style="font-family:monospace;"> </span><%</span># implies data binding. But, as I said, <span style="background: rgb(255, 238, 98) none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><%</span>= doesn't work either. Sure, I can assign values to Maks properties programmatically in code-behind file, but it sounds crazy, given the fact that MaskEditExtender controls are scattered inside many other controls in a complicated page.<br /><br />So, again: is there a way to decoratively set an attribute of a server-side control to some public property/value (defined in code-behind code or in a Business Layer)?<br />Suprizingly, I couldn't find any information on a Web....Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com2tag:blogger.com,1999:blog-17567386.post-2033480579813210842008-09-04T10:05:00.000-04:002008-09-04T11:18:55.338-04:00Custom ViewState storage and multiple browser tabs/windowsI'm thinking about implementing a custom ViewState storage, most likely - in a database, like it is described in <a href="http://blog.arctus.co.uk/articles/2007/04/23/advanced-asp-net-storing-viewstate-in-a-database">this article</a>. It may do several good things: make pages more lightweight, together with <span><span class="Article_Title"><a href="http://www.odetocode.com/Articles/421.aspx">Cross Page Post Back</a></span></span> allow for implementing <a href="http://www.strong-point.com/Blogs/tabid/87/EntryID/8/Default.aspx">Post/Redirect/Get</a> (PRG) pattern in ASP.NET application, maybe even allow for some custom history / breadcrumb solutions for application / page lifecycle...<div>However, I have one concern: having multiple browser's Tabs or windows. When you work in Internet Explorer, you can open a new tab and have it to work with the same ASP.NET application, it will share session. With Firefox, you can even open a new window and it will share session. Now, if we use links (GET operation) to go from page to page, GUID is not passed between pages, and custom history / breadcrumb cannot work correctly with multiple Tabs. The only (ugly) solution I see is to modify every link on ASP.NET page to include GUID.</div>Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-19582383023801214852008-08-19T01:56:00.005-04:002008-09-12T16:14:02.181-04:00Delegates and events. What does `event` keyword actually mean in C#<div xmlns="http://www.w3.org/1999/xhtml">In a very interesting "<a href="http://www.amazon.com/gp/product/1590598733/">Accelerated C# 2008</a>" book, its author Trey Nash described the role of C# events (page 262):<br />"... <span style="color: rgb(0, 0, 102);">.NET runtime designers were so generous as to define a formalized built-in event mechanism. When you declare an event within a class, internally the compiler implements some hidden methods that allow you to register and unregister delegates, which are called when a specific event is raised. In essence, an event is a shortcut that saves you the time of having to write the register and unregister methods that manage a delegate chain yourself.</span>"<br />Then, on a page 265 he is saying:<br />"... <span style="color: rgb(0, 0, 102);">events are ideal for implementing a publish/subscribe design pattern, where many listeners are registering for notification (publication) of an event. Similarly, you can use .NET events to implement a form of the Observer pattern, where various entities register to receive notifications that some other entity has changed.</span>"<br /><br />Often, when some material is not clear to me, I try to read another book to clarify a matter. So, I found the following description of events in "<a href="http://www.amazon.com/3-0-Nutshell-Desktop-Reference-OReilly/dp/0596527578/">C# 3.0 in a Nutshell</a>" book (page 112:<br />"<span style="color: rgb(0, 0, 102);">When using delegates, two emergent roles commonly appear: </span><span style="font-style: italic; color: rgb(0, 0, 102);">broadcaster</span><span style="color: rgb(0, 0, 102);"> and </span><span style="font-style: italic; color: rgb(0, 0, 102);">subscriber</span><span style="color: rgb(0, 0, 102);">.</span><br /><span style="color: rgb(0, 0, 102);">The </span><span style="font-style: italic; color: rgb(0, 0, 102);">broadcaster</span><span style="color: rgb(0, 0, 102);"> is a type that contains a delegate field. The broadcaster decides when to broadcast, by invoking the delegate.</span><br /><span style="color: rgb(0, 0, 102);">The </span><span style="font-style: italic; color: rgb(0, 0, 102);">subscribers</span><span style="color: rgb(0, 0, 102);"> are the method target recipients. A subscriber decides when to start and stop listening, by calling += and -= on the broadcaster's delegate. A subscriber does not know about, or interfere with, other subscribers.</span><br /><span style="color: rgb(0, 0, 102);">Events are a language feature that formalizes this pattern. An event is a wrapper for a delegate that exposes just the subset of delegate features required for the broadcaster/subscriber model. The main purpose of events is </span><span style="font-style: italic; color: rgb(0, 0, 102);">to prevent subscribers from interfering with each other</span><span style="color: rgb(0, 0, 102);">.</span>"<br /><br />This is quite opposite to what Trey said about events! They are introduced <span style="font-style: italic;">to prevent subscribers from interfering with each other</span>, not as <span style="font-style: italic;">a shortcut that saves you the time of having to write the register and unregister methods</span>.<br />+= and -= operators are defined for non-event delegates as well as for event delegates, while non-event delegates also expose assignment (=) operator and GetInvocationList() method which are too dangerous for subscribers. They allow a particular subscriber to investigate which other classes also subscribed to the same delegate and even allow to remove other independent subscribers. That's exactly what we prevent by adding an `event` keyword to a delegate.<br /><br />Here's a modified code snippet from "C# 3.0 in a Nutshell" which proves what I said above (note, that it does not use famous <a href="http://msdn.microsoft.com/en-us/library/db0etb8x.aspx">EventHandler<TEventArgs></a> delegates; events could actually be used with any delegates):<br /><br /><pre><!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red128\green128\blue128;\red0\green128\blue0;\red163\green21\blue21;}??\fs20 \cf1 using\cf0 System;\par ??\cf1 using\cf0 System.Collections.Generic;\par ??\cf1 using\cf0 System.Linq;\par ??\cf1 using\cf0 System.Text;\par ??\par ??\cf1 namespace\cf0 Chp04_events \{\par ??\par ?? \cf1 internal\cf0 \cf1 delegate\cf0 \cf1 void\cf0 \cf4 PriceChangedHandler\cf0 ( \cf1 decimal\cf0 oldPrice, \cf1 decimal\cf0 newPrice );\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 "Broadcaster" class\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf1 internal\cf0 \cf1 class\cf0 \cf4 Stock\cf0 \{\par ?? \cf1 string\cf0 _symbol;\par ?? \cf1 decimal\cf0 _price;\par ??\par ?? \cf1 public\cf0 Stock( \cf1 string\cf0 symbol ) \{ \cf1 this\cf0 ._symbol = symbol; \}\par ??\par ?? \cf6 // If you comment out this line and uncomment next line, "myStock.PriceChanged = ..." and "Delegate[] chain = " statements\par ??\cf0 \cf6 // below in public void SetStockToWatch( Stock myStock ) methods would become legal, compromising an independence of event subscribers.\par ??\cf0 \cf6 // That's why we use an `event` keyword, rather than simpli a delegate.\par ??\cf0 \cf1 public\cf0 \cf1 event\cf0 \cf4 PriceChangedHandler\cf0 PriceChanged;\par ?? \cf6 //public PriceChangedHandler PriceChanged;\par ??\par ??\cf0 \cf1 public\cf0 \cf1 decimal\cf0 Price \{\par ?? \cf1 get\cf0 \{ \cf1 return\cf0 _price; \}\par ?? \cf1 set\cf0 \{\par ?? \cf1 if\cf0 (_price == \cf1 value\cf0 ) \cf1 return\cf0 ;\par ?? \cf1 if\cf0 (PriceChanged != \cf1 null\cf0 ) \{\par ?? \cf6 // Code within the Broadcaster type has full access to event and can treat it as delegate:\par ??\cf0 \cf4 Delegate\cf0 [] chain = PriceChanged.GetInvocationList();\par ?? \cf4 Console\cf0 .WriteLine( \cf7 "There is/are \{0\} subscribers watching for event I'm broadcsting"\cf0 , chain.Length );\par ?? \cf4 Console\cf0 .WriteLine( \cf7 "The first subscriber has a type of \{0\}"\cf0 , chain[0].Target.GetType() );\par ?? \cf1 if\cf0 (chain.Length > 1) \{\par ?? \cf4 Console\cf0 .WriteLine( \cf7 "The second subscriber has a type of \{0\}"\cf0 , chain[1].Target.GetType() );\par ?? \}\par ??\par ?? PriceChanged( _price, \cf1 value\cf0 );\par ?? \}\par ?? _price = \cf1 value\cf0 ;\par ?? \}\par ?? \}\par ?? \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 "Subscriber" class\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf1 internal\cf0 \cf1 class\cf0 \cf4 StockWatcher\cf0 \{\par ?? \cf1 protected\cf0 \cf1 string\cf0 _watcherName = \cf4 String\cf0 .Empty;\par ??\par ?? \cf1 public\cf0 StockWatcher( \cf1 string\cf0 watcherName ) \{\par ?? \cf1 this\cf0 ._watcherName = watcherName;\par ?? \}\par ??\par ?? \cf1 public\cf0 \cf1 string\cf0 WatcherName \{\par ?? \cf1 get\cf0 \{ \cf1 return\cf0 _watcherName; \}\par ?? \}\par ??\par ?? \cf1 public\cf0 \cf1 void\cf0 SetStockToWatch( \cf4 Stock\cf0 myStock ) \{\par ?? myStock.PriceChanged += \cf1 new\cf0 \cf4 PriceChangedHandler\cf0 ( myStock_PriceChanged );\par ?? \cf6 // Code outside the Broadcaster type can only perform += an -=. "Subscriber" does not know about other "subscribers".\par ??\cf0 \cf6 // The followig commented out code won't compile:\par ??\par ??\cf0 \cf6 // Error: The event 'Chp04_events.Stock.PriceChanged' can only appear on the left hand side of += or -=\par ??\cf0 \cf6 // (except when used from within the type 'Chp04_events.Stock')\par ??\cf0 myStock.PriceChanged = \cf1 new\cf0 \cf4 PriceChangedHandler\cf0 ( myStock_PriceChanged );\par ?? \cf6 // The same error:\par ??\cf0 \cf4 Delegate\cf0 [] chain = myStock.PriceChanged.GetInvocationList();\par ?? \}\par ??\par ?? \cf1 public\cf0 \cf1 void\cf0 myStock_PriceChanged( \cf1 decimal\cf0 oldPrice, \cf1 decimal\cf0 newPrice ) \{\par ?? \cf4 Console\cf0 .WriteLine( \cf7 "\{0\}: Stock price was changed from \{1\} to \{2\}"\cf0 , WatcherName, oldPrice, newPrice );\par ?? \}\par ?? \}\par ??\par ?? \cf1 internal\cf0 \cf1 class\cf0 \cf4 NewStockWatcher\cf0 : \cf4 StockWatcher\cf0 \{\par ?? \cf1 public\cf0 NewStockWatcher( \cf1 string\cf0 watcherName ) : \cf1 base\cf0 ( watcherName ) \{ \}\par ?? \}\par ??\par ?? \cf1 class\cf0 \cf4 Program\cf0 \{\par ?? \cf1 static\cf0 \cf1 void\cf0 Main( \cf1 string\cf0 [] args ) \{\par ?? \cf1 decimal\cf0 myDecPrice;\par ??\par ?? \cf1 var\cf0 myStock = \cf1 new\cf0 \cf4 Stock\cf0 ( \cf7 "Napster"\cf0 );\par ?? \cf1 var\cf0 myStockWatcher1 = \cf1 new\cf0 \cf4 StockWatcher\cf0 ( \cf7 "First Watcher"\cf0 );\par ?? \cf1 var\cf0 myStockWatcher2 = \cf1 new\cf0 \cf4 NewStockWatcher\cf0 ( \cf7 "Second Watcher"\cf0 );\par ??\par ?? myStockWatcher1.SetStockToWatch( myStock );\par ?? myStockWatcher2.SetStockToWatch( myStock );\par ??\par ?? \cf1 while\cf0 (1 == 1) \{\par ?? \cf4 Console\cf0 .WriteLine( \cf7 "Please enter new stock price:"\cf0 );\par ?? \cf1 string\cf0 newStockPrice = \cf4 Console\cf0 .ReadLine();\par ?? \cf1 if\cf0 (newStockPrice == \cf4 String\cf0 .Empty) \cf1 break\cf0 ;\par ?? \cf1 if\cf0 (\cf4 Decimal\cf0 .TryParse( newStockPrice, \cf1 out\cf0 myDecPrice ))\par ?? myStock.Price = myDecPrice;\par ?? \}\par ?? \}\par ?? \}\par ??\}\par ??} --><br /><div style="background: white none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Courier New;font-size:10pt;color:black;"><pre style="margin: 0px;"><span style="color:blue;">using</span> System;</pre><pre style="margin: 0px;"><span style="color:blue;">using</span> System.Collections.Generic;</pre><pre style="margin: 0px;"><span style="color:blue;">using</span> System.Linq;</pre><pre style="margin: 0px;"><span style="color:blue;">using</span> System.Text;</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"><span style="color:blue;">namespace</span> Chp04_events {</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">internal</span> <span style="color:blue;">delegate</span> <span style="color:blue;">void</span> <span style="color: rgb(43, 145, 175);">PriceChangedHandler</span>( <span style="color:blue;">decimal</span> oldPrice, <span style="color:blue;">decimal</span> newPrice );</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:gray;">///</span><span style="color:green;"> </span><span style="color:gray;"><summary></span></pre><pre style="margin: 0px;"> <span style="color:gray;">///</span><span style="color:green;"> "Broadcaster" class</span></pre><pre style="margin: 0px;"> <span style="color:gray;">///</span><span style="color:green;"> </span><span style="color:gray;"></summary></span></pre><pre style="margin: 0px;"> <span style="color:blue;">internal</span> <span style="color:blue;">class</span> <span style="color: rgb(43, 145, 175);">Stock</span> {</pre><pre style="margin: 0px;"> <span style="color:blue;">string</span> _symbol;</pre><pre style="margin: 0px;"> <span style="color:blue;">decimal</span> _price;</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> Stock( <span style="color:blue;">string</span> symbol ) { <span style="color:blue;">this</span>._symbol = symbol; }</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:green;">// If you comment out this line and uncomment next line, "myStock.PriceChanged = ..." and "Delegate[] chain = " statements</span></pre><pre style="margin: 0px;"> <span style="color:green;">// below in public void SetStockToWatch( Stock myStock ) methods would become legal, compromising an independence of event subscribers.</span></pre><pre style="margin: 0px;"> <span style="color:green;">// That's why we use an `event` keyword, rather than simpli a delegate.</span></pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">event</span> <span style="color: rgb(43, 145, 175);">PriceChangedHandler</span> PriceChanged;</pre><pre style="margin: 0px;"> <span style="color:green;">//public PriceChangedHandler PriceChanged;</span></pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">decimal</span> Price {</pre><pre style="margin: 0px;"> <span style="color:blue;">get</span> { <span style="color:blue;">return</span> _price; }</pre><pre style="margin: 0px;"> <span style="color:blue;">set</span> {</pre><pre style="margin: 0px;"> <span style="color:blue;">if</span> (_price == <span style="color:blue;">value</span>) <span style="color:blue;">return</span>;</pre><pre style="margin: 0px;"> <span style="color:blue;">if</span> (PriceChanged != <span style="color:blue;">null</span>) {</pre><pre style="margin: 0px;"> <span style="color:green;">// Code within the Broadcaster type has full access to event and can treat it as delegate:</span></pre><pre style="margin: 0px;"> <span style="color: rgb(43, 145, 175);">Delegate</span>[] chain = PriceChanged.GetInvocationList();</pre><pre style="margin: 0px;"> <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine( <span style="color: rgb(163, 21, 21);">"There is/are {0} subscribers watching for event I'm broadcsting"</span>, chain.Length );</pre><pre style="margin: 0px;"> <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine( <span style="color: rgb(163, 21, 21);">"The first subscriber has a type of {0}"</span>, chain[0].Target.GetType() );</pre><pre style="margin: 0px;"> <span style="color:blue;">if</span> (chain.Length > 1) {</pre><pre style="margin: 0px;"> <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine( <span style="color: rgb(163, 21, 21);">"The second subscriber has a type of {0}"</span>, chain[1].Target.GetType() );</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> PriceChanged( _price, <span style="color:blue;">value</span> );</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> _price = <span style="color:blue;">value</span>;</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:gray;">///</span><span style="color:green;"> </span><span style="color:gray;"><summary></span></pre><pre style="margin: 0px;"> <span style="color:gray;">///</span><span style="color:green;"> "Subscriber" class</span></pre><pre style="margin: 0px;"> <span style="color:gray;">///</span><span style="color:green;"> </span><span style="color:gray;"></summary></span></pre><pre style="margin: 0px;"> <span style="color:blue;">internal</span> <span style="color:blue;">class</span> <span style="color: rgb(43, 145, 175);">StockWatcher</span> {</pre><pre style="margin: 0px;"> <span style="color:blue;">protected</span> <span style="color:blue;">string</span> _watcherName = <span style="color: rgb(43, 145, 175);">String</span>.Empty;</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> StockWatcher( <span style="color:blue;">string</span> watcherName ) {</pre><pre style="margin: 0px;"> <span style="color:blue;">this</span>._watcherName = watcherName;</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">string</span> WatcherName {</pre><pre style="margin: 0px;"> <span style="color:blue;">get</span> { <span style="color:blue;">return</span> _watcherName; }</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">void</span> SetStockToWatch( <span style="color: rgb(43, 145, 175);">Stock</span> myStock ) {</pre><pre style="margin: 0px;"> myStock.PriceChanged += <span style="color:blue;">new</span> <span style="color: rgb(43, 145, 175);">PriceChangedHandler</span>( myStock_PriceChanged );</pre><pre style="margin: 0px;"> <span style="color:green;">// Code outside the Broadcaster type can only perform += an -=. "Subscriber" does not know about other "subscribers".</span></pre><pre style="margin: 0px;"> <span style="color:green;">// The following line of code won't compile:</span> </pre><pre style="margin: 0px;"> <span style="color:green;">// Error: The event 'Chp04_events.Stock.PriceChanged' can only appear on the left hand side of += or -=</span></pre><pre style="margin: 0px;"> <span style="color:green;">// (except when used from within the type 'Chp04_events.Stock')</span></pre><pre style="margin: 0px;"> myStock.PriceChanged = <span style="color:blue;">new</span> <span style="color: rgb(43, 145, 175);">PriceChangedHandler</span>( myStock_PriceChanged );</pre><pre style="margin: 0px;"> <span style="color:green;">// The same error:</span></pre><pre style="margin: 0px;"> <span style="color: rgb(43, 145, 175);">Delegate</span>[] chain = myStock.PriceChanged.GetInvocationList();</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> <span style="color:blue;">void</span> myStock_PriceChanged( <span style="color:blue;">decimal</span> oldPrice, <span style="color:blue;">decimal</span> newPrice ) {</pre><pre style="margin: 0px;"> <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine( <span style="color: rgb(163, 21, 21);">"{0}: Stock price was changed from {1} to {2}"</span>, WatcherName, oldPrice, newPrice );</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">internal</span> <span style="color:blue;">class</span> <span style="color: rgb(43, 145, 175);">NewStockWatcher</span> : <span style="color: rgb(43, 145, 175);">StockWatcher</span> {</pre><pre style="margin: 0px;"> <span style="color:blue;">public</span> NewStockWatcher( <span style="color:blue;">string</span> watcherName ) : <span style="color:blue;">base</span>( watcherName ) { }</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">class</span> <span style="color: rgb(43, 145, 175);">Program</span> {</pre><pre style="margin: 0px;"> <span style="color:blue;">static</span> <span style="color:blue;">void</span> Main( <span style="color:blue;">string</span>[] args ) {</pre><pre style="margin: 0px;"> <span style="color:blue;">decimal</span> myDecPrice;</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">var</span> myStock = <span style="color:blue;">new</span> <span style="color: rgb(43, 145, 175);">Stock</span>( <span style="color: rgb(163, 21, 21);">"Napster"</span> );</pre><pre style="margin: 0px;"> <span style="color:blue;">var</span> myStockWatcher1 = <span style="color:blue;">new</span> <span style="color: rgb(43, 145, 175);">StockWatcher</span>( <span style="color: rgb(163, 21, 21);">"First Watcher"</span> );</pre><pre style="margin: 0px;"> <span style="color:blue;">var</span> myStockWatcher2 = <span style="color:blue;">new</span> <span style="color: rgb(43, 145, 175);">NewStockWatcher</span>( <span style="color: rgb(163, 21, 21);">"Second Watcher"</span> );</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> myStockWatcher1.SetStockToWatch( myStock );</pre><pre style="margin: 0px;"> myStockWatcher2.SetStockToWatch( myStock );</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color:blue;">while</span> (1 == 1) {</pre><pre style="margin: 0px;"> <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine( <span style="color: rgb(163, 21, 21);">"Please enter new stock price:"</span> );</pre><pre style="margin: 0px;"> <span style="color:blue;">string</span> newStockPrice = <span style="color: rgb(43, 145, 175);">Console</span>.ReadLine();</pre><pre style="margin: 0px;"> <span style="color:blue;">if</span> (newStockPrice == <span style="color: rgb(43, 145, 175);">String</span>.Empty) <span style="color:blue;">break</span>;</pre><pre style="margin: 0px;"> <span style="color:blue;">if</span> (<span style="color: rgb(43, 145, 175);">Decimal</span>.TryParse( newStockPrice, <span style="color:blue;">out</span> myDecPrice ))</pre><pre style="margin: 0px;"> myStock.Price = myDecPrice;</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;">}</pre></div></pre></div>Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-68277047830341389982008-08-15T10:47:00.000-04:002008-08-15T10:50:24.625-04:00"ASP.NET gets no Respect" by Rick StrahlThere is a good <a href="http://www.west-wind.com/weblog/ShowPost.aspx?id=453551">ASP.NET gets no Respect </a>article just posted by well-known ASP.NET developer Rick Strahl. Read it! I commented there too :)Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com3tag:blogger.com,1999:blog-17567386.post-11550996095065856592008-08-14T23:53:00.003-04:002008-08-15T00:05:15.293-04:00A novice Scala programmer: Eclipse vs. IntelliJ IDEA vs. Netbeans. Debugger and for () yield {}<div xmlns="http://www.w3.org/1999/xhtml">I continue my <a href="http://pro-thoughts.blogspot.com/2008/07/novice-scala-programmer-eclipse-vs.html">Scala IDE mini series</a> I described my experience with installation of Eclipse, IntelliJ IDEA, and Netbeans applications and installation of Scala plugins in those environments.<br /><br />The following simple code (from <a href="http://www.artima.com/shop/programming_in_scala">Programming in Scala</a>, chapter 7) poses certain challendges to Scala debuggers. Some debuggers cannot stop on breakpoint placed, for example, on "val prod = (i * j).toString" line.<br />As Alexander Podkhalyuzin from JetBRAINS/Intellij IDEA Scala Plugin team <a href="http://www.intellij.net/forums/thread.jspa?threadID=276589&tstart=0">said</a>, "This problem goes to Java debugger problem with anonymous classes, because it's compile in different class file. So, we must to understand what name of this class files, and to set to each line, line in this class file. In Eclipse developers do this work, we have not implemented this yet, but you must be sure, it will be, because it is not convenient to work without for debugger."<br /><br />As of today, <a href="http://www.scala-lang.org/tools/eclipse/index.html">Eclipse Scala plugin</a> debugger can stop, the latest <a href="http://plugins.intellij.net/plugin/?id=1347">Intellij IDEA Scala Plugin</a> debugger can stop as well. Both go even to a library Seq.class; Eclipse shows its code, IntelliJ IDEA shows interface, saying that it is "IntelliJ API Decompiler stub source generated from a class file. Implementation of methods is not available".<br />The latest and greatly improved <a href="http://wiki.netbeans.org/Scala">NetBeans Scala plugin</a> debugger still cannot stop here.<br /><br /><pre><br />package chp7multitable<br />object Main {<br />/**<br />* @param args the command line arguments<br />*/<br /> def main(args: Array[String]) = {<br /> val multi = {<br /> val table = for (i <- 1 to 10) yield {<br /> val row = for (j <- 1 to 10) yield {<br /><b><span style="color: rgb(204, 0, 0);">°</span></b> <b> val prod = (i * j).toString</b><br /> String.format("%4s", Array(prod))<br /> }<br /> row.mkString + "\n"<br /> }<br /> table.mkString<br /> }<br /> println(multi)<br /> }<br />}</pre><br /><br /><br />1. <a href="http://pro-thoughts.blogspot.com/2008/07/novice-scala-programmer-eclipse-vs.html">Eclipse vs. IntelliJ IDEA vs. Netbeans. Installation.</a><br />2. <a href="http://pro-thoughts.blogspot.com/2008/07/novice-scala-programmer-eclipse-vs_30.html">Eclipse vs. IntelliJ IDEA vs. Netbeans. Creating and running Scala project with Eclipse.</a><br />3. <a href="http://pro-thoughts.blogspot.com/2008/07/novice-scala-programmer-eclipse-vs_9647.html">Eclipse vs. IntelliJ IDEA vs. Netbeans. Creating and running Scala project with IntelliJ IDEA.</a><br />4. <a href="http://pro-thoughts.blogspot.com/2008/07/novice-scala-programmer-eclipse-vs_31.html">Eclipse vs. IntelliJ IDEA vs. Netbeans. Creating and running Scala project with Netbeans.</a><br />5. <a href="http://pro-thoughts.blogspot.com/2008/07/novice-scala-programmer-eclipse-vs_3251.html">A novice Scala programmer: Eclipse vs. IntelliJ IDEA vs. Netbeans.</a><br />6. A novice Scala programmer: Eclipse vs. IntelliJ IDEA vs. Netbeans. Debugger and for () yield {}.<br /></div>Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-87795601599653366752008-08-07T05:40:00.002-04:002008-08-07T09:46:18.440-04:00Effective Java Programming<div xmlns="http://www.w3.org/1999/xhtml">Here's an interesting <a href="http://www.youtube.com/watch?v=ZOwHiGCzZjo">speech by Joshua Bloch</a> (the author of <a href="http://java.sun.com/docs/books/effective/">Effective Java</a>) on YouTube.<br /><br />(I use <a href="http://www.scribefire.com/">ScribeFire</a> with Firefox to post on Blogger. Unfortunately, ScribeFire always posts as Draft, regardless of me selecting or un-selecting post-to-draft option.)<br /></div>Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0tag:blogger.com,1999:blog-17567386.post-39556001135073146882008-08-02T04:01:00.002-04:002008-08-02T04:06:51.908-04:00A couple of excellent Scala resources<div xmlns="http://www.w3.org/1999/xhtml">Here's a very live and professional <a href="http://www.nabble.com/Scala-Programming-Language-f20934.html">Scala forum</a>. I asked a question there and immediately got a qualified answer from this wonderful <a href="http://projects.workingmouse.com/public/intro-to-highlevel-programming-with-scala/artifacts/latest/chunk-html/index.html">Scala pro</a>.<br /><br />BTW.: I'm writing this post using <a href="http://www.scribefire.com/">this tool</a>. Seems to be more convenient that Blogger itself.<br /></div>Владимирhttp://www.blogger.com/profile/00331194583266302228noreply@blogger.com0