tag:blogger.com,1999:blog-56117069233565520902024-03-04T23:08:07.470-05:00C Razor Sharp / C# / .NETA.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.comBlogger28125tag:blogger.com,1999:blog-5611706923356552090.post-91209819061893552502012-02-15T15:12:00.009-05:002012-02-15T15:45:28.049-05:00Passing variables from your Controller to your JavaScript in ASP.NET MVC<span style="font-weight:bold;">GitHub link to NGon:</span> <a href="https://github.com/brooklynDev/NGon">https://github.com/brooklynDev/NGon</a><br /><br />Last night I was watching the latest RailCast screen cast, where Ryan showed a cool technique in Ruby on Rails on how to pass data from your Controller straight to your JavaScript:<br /><br /><a href="http://railscasts.com/episodes/324-passing-data-to-javascript">http://railscasts.com/episodes/324-passing-data-to-javascript</a><br /><br />Essentially, it involved using a gem called <a href="https://github.com/gazay/gon">Gon</a> which enabled you to do this in your controller:<br /><br /><script src="https://gist.github.com/1838771.js"> </script><br /><br />I thought that was pretty cool, and it'd be awesome to have the same thing in ASP.NET MVC. Enter <span style="font-weight:bold;">NGon</span>. The code is actually very simple, but I think the usage is quite elegant (It's up on GitHub <a href="https://github.com/brooklynDev/NGon">here</a>, complete with Unit Tests and a sample app).<br /><br /><h1>Usage:</h1><br />The first step is to register the NGonActionFilterAttribute in the global filters in your Global.asax.cs page:<br /><br /><script src="https://gist.github.com/1838799.js"> </script><br /><br />Then, in your Controller, you do this:<br /><br /><script src="https://gist.github.com/1838802.js"> </script><br /><br />Next, in your HTML page (probably in your Layout.cshtml page so it's available everywhere) you add this line:<br /><br /><span style="font-weight:bold;"><br />@Html.IncludeNGon()</span><br /><br />At this point, you'll now have access to the values in your javascript:<br /><br /><script src="https://gist.github.com/1838811.js"> </script><br /><br />The cool thing is that it works on more than just simple types. It works on any object which in turn gets serialized into JSON (using the JavascriptSerializer). This allows you to do something like this:<br /><br /><script src="https://gist.github.com/1838825.js"> </script><br /><br />and in your javascript:<br /><br /><script src="https://gist.github.com/1838833.js"> </script><br /><br /><h1>Under the hood: </h1><br /><br />It's actually all quite simple. The first thing that happpens, is when an action gets called, the NGonActionFilterAttribute fires, and it creates a new ExpandoObject called NGon on the Controllers ViewBag property:<br /><br /><script src="https://gist.github.com/1838845.js"> </script><br /><br />Then, as you keep adding items to the ViewBag.NGon property, you're adding it to this underlying ExpandoObject. Finally, when you call the IncludeNGon in the HTML, this is where all the magic happens:<br /><br /><script src="https://gist.github.com/1838853.js"> </script><br /><br />What it does is, it first creates an empty javascript object on the window object. Then, for each property in the ViewBag.NGon property, it adds the serialized version of it to that javascript object on the window object. What you end up with, is something like this:<br /><br /><script src="https://gist.github.com/1838874.js"> </script><br /><br />Cool huh? Drop me a comment, let me know what you think!A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com5tag:blogger.com,1999:blog-5611706923356552090.post-5859937248432936522011-03-11T00:05:00.003-05:002011-03-11T00:59:25.836-05:00Master Page Model in ASP.NET MVC 3 using Dependency Injection (Unity)<span style="font-weight:bold;">Link to source code:</span> <a href="http://www.box.net/shared/ujfbu1ig9z">http://www.box.net/shared/ujfbu1ig9z</a><br /><br />A common problem many developers face when creating ASP.NET MVC applications, is when you need some data in your Master Page (I know they're called "Layout" pages in Razor, but from here on out I'll be referring to them as Master Pages). The problem comes up when you need to have some dynamic data in the Master Page itself (think of a Shopping Cart example, where you want to display the current count of items in the cart) but since we ever only send data from the Controllers to the Views themselves, how does the Master Page get the data that <span style="font-style:italic;">it</span> needs. <br /><br />I know there are many solutions out there, and I'm not saying any of them are good or bad, I'm just here to show another way of doing it, using Dependency Injection. For this example, I'll be demoing a use case of where we want to display my last 5 tweets on the Master Page. This is the final result:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/2037392_master-page-model.jpg" style="width:879px;height:384px;"/><br /><br />The right hand side under Index is the Index View, but on the left hand side, the "left nav" is where the twitter feed sits, and that data we want to display on every page, and will therefore come from the master page.<br /><br />In ASP.NET MVC 3, Dependency Injection has become very easy. Now all you need to do is to implement your own IDependencyResolver, and let the framework know to use your custom resolver when it needs to build up Controllers and such. Here's a typical implementation using Unity:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> UnityDependencyResolver : IDependencyResolver<br /> {<br /> <span class="kwrd">private</span> <span class="kwrd">readonly</span> IUnityContainer _unityContainer;<br /><br /> <span class="kwrd">public</span> UnityDependencyResolver(IUnityContainer unityContainer)<br /> {<br /> _unityContainer = unityContainer;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">object</span> GetService(Type serviceType)<br /> {<br /> <span class="kwrd">if</span> (!_unityContainer.IsRegistered(serviceType))<br /> {<br /> <span class="kwrd">if</span> (serviceType.IsAbstract || serviceType.IsInterface)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">null</span>;<br /> }<br /> }<br /><br /> <span class="kwrd">return</span> _unityContainer.Resolve(serviceType);<br /> }<br /><br /> <span class="kwrd">public</span> IEnumerable<<span class="kwrd">object</span>> GetServices(Type serviceType)<br /> {<br /> <span class="kwrd">return</span> _unityContainer.ResolveAll(serviceType);<br /> }<br /> }</pre><br /><br />Not much to explain on this one, except that with Unity there's no "TryResolve" (actually there is in the Prism Codeplex project, but all that does is wrap a try/catch) so therefore we need to make sure we can resolve the type before we actually call Resolve.<br /><br />Now let's start building on top of that. I created an interface called IMasterPageDataRetriever. It's responsibility is simply to get data that the Master Page needs. In this case, it'll call out to a Service that calls Twitter to retrieve my last 5 tweets (incidentally, NuGet is AWESOME for this kind of stuff. I just typed in "Twitter" in the Search box in Nuget, and picked the one that looked the most popular "TweetSharp". Cool stuff).<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">interface</span> IMasterPageDataRetriever<br /> {<br /> <span class="kwrd">object</span> GetMasterPageData();<br /> }</pre><br /><br />Here's the implementation:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> MasterPageDataSetter : IMasterPageDataRetriever<br /> {<br /> <span class="kwrd">private</span> <span class="kwrd">readonly</span> ITweetRetriever _tweetRetriever;<br /><br /> <span class="kwrd">public</span> MasterPageDataSetter(ITweetRetriever tweetRetriever)<br /> {<br /> _tweetRetriever = tweetRetriever;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">object</span> GetMasterPageData()<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">new</span> TweetViewModel(_tweetRetriever.GetTweets(<span class="str">"@brooklynDev"</span>, 5));<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Tweet<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">string</span> UserName { get; set; }<br /> <span class="kwrd">public</span> <span class="kwrd">string</span> Message { get; set; }<br /> <span class="kwrd">public</span> DateTime Timestamp { get; set; }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">interface</span> ITweetRetriever<br /> {<br /> IEnumerable<Tweet> GetTweets(<span class="kwrd">string</span> userName, <span class="kwrd">int</span> maxAmount);<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> TweetRetriever : ITweetRetriever<br /> {<br /> <span class="kwrd">public</span> IEnumerable<Tweet> GetTweets(<span class="kwrd">string</span> userName, <span class="kwrd">int</span> maxAmount)<br /> {<br /> var service = <span class="kwrd">new</span> TwitterService();<br /> var result = service.ListTweetsOnSpecifiedUserTimeline(userName, maxAmount);<br /> <span class="kwrd">return</span> result.Select(r => <span class="kwrd">new</span> Tweet<br /> {<br /> Message = r.TextAsHtml,<br /> Timestamp = r.CreatedDate,<br /> UserName = userName<br /> });<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> TweetViewModel<br /> {<br /> <span class="kwrd">public</span> TweetViewModel(IEnumerable<Tweet> tweets)<br /> {<br /> <span class="kwrd">this</span>.Tweets = tweets.Select(t => t.Message);<br /> <span class="kwrd">this</span>.UserName = tweets.First().UserName;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">string</span> UserName { get; set; }<br /> <span class="kwrd">public</span> IEnumerable<<span class="kwrd">string</span>> Tweets { get; set; }<br /><br /> }</pre><br /><br />Not much code, but the point here is, I have an implementation of an IMasterPageDataRetriever that gets injected with an ITweetRetriever, calls that TweetRetriever and that returns a ViewModel that has the tweets in it. So far this is all pretty straight forward, very common stuff that you see in all apps that use loose coupling. <br /><br />The questions now however, is how does the Master Page get a hold of this TweetViewModel? The trick is in the Dependency Resolver. Here's the updated code, I'll do my best to explain:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> UnityDependencyResolver : IDependencyResolver<br /> {<br /> <span class="kwrd">private</span> <span class="kwrd">readonly</span> IUnityContainer _unityContainer;<br /><br /> <span class="kwrd">public</span> UnityDependencyResolver(IUnityContainer unityContainer)<br /> {<br /> _unityContainer = unityContainer;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">object</span> GetService(Type serviceType)<br /> {<br /> <span class="kwrd">if</span>(!_unityContainer.IsRegistered(serviceType))<br /> {<br /> <span class="kwrd">if</span>(serviceType.IsAbstract || serviceType.IsInterface)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">null</span>;<br /> }<br /> }<br /><br /> var result = _unityContainer.Resolve(serviceType);<br /> var controller = result <span class="kwrd">as</span> ControllerBase;<br /> <span class="kwrd">if</span>(controller == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">return</span> result;<br /> }<br /> <span class="kwrd">try</span><br /> {<br /> var masterPageDataSetter = _unityContainer.Resolve<IMasterPageDataRetriever>();<br /> controller.ViewBag.MasterPageModel = masterPageDataSetter.GetMasterPageData();<br /> <span class="kwrd">return</span> controller;<br /> }<br /> <span class="kwrd">catch</span><br /> {<br /> <span class="kwrd">return</span> result;<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> IEnumerable<<span class="kwrd">object</span>> GetServices(Type serviceType)<br /> {<br /> <span class="kwrd">return</span> _unityContainer.ResolveAll(serviceType);<br /> }<br /> }</pre><br /><br />What's happening here is that instead of just returning what we got out of the container, we first check if it's a Controller (if it can be assigned to a ControllerBase). If it is, we cast it to a ControllerBase, at which point we use the ViewBag property, and set the data we get from our IMasterPageDataRetriever (pulled out of the container) to a (dynamic) property on the ViewBag called "MasterPageModel". In order for this to work, you need to make sure you're correctly configuring your container:<br /><br />In my Global.asax I have this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">protected</span> <span class="kwrd">void</span> Application_Start()<br /> {<br /> AreaRegistration.RegisterAllAreas();<br /><br /> RegisterGlobalFilters(GlobalFilters.Filters);<br /> RegisterRoutes(RouteTable.Routes);<br /><br /> DependencyResolver.SetResolver(<span class="kwrd">new</span> UnityDependencyResolver(GetConfiguredContainer()));<br /> }<br /><br /> <span class="kwrd">private</span> IUnityContainer GetConfiguredContainer()<br /> {<br /> var container = <span class="kwrd">new</span> UnityContainer();<br /> container.RegisterType<ITweetRetriever, TweetRetriever>();<br /> container.RegisterType<IMasterPageDataRetriever, MasterPageDataSetter>();<br /> <span class="kwrd">return</span> container;<br /> }</pre><br /><br />I'm registering all the dependencies I need, including the IMasterPageDataRetriever. <br /><br />Now, in order to use this data, here's what we do in our Master Page (I'm using the Razor view engine, but this can obviously be applied to any View Engine):<br /><br />First, I created a Partial View that will actually display the Tweets. It's strongly typed to the TweetViewModel type:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br />@model MasterPageModelDemo.Web.Models.TweetViewModel<br /><br /><span class="kwrd"><</span><span class="html">h4</span><span class="kwrd">></span>@this.Model.UserName<span class="kwrd"></</span><span class="html">h4</span><span class="kwrd">></span><br /><span class="kwrd"><</span><span class="html">ul</span><span class="kwrd">></span><br /> @foreach(var tweet in this.Model.Tweets)<br /> {<br /> <span class="kwrd"><</span><span class="html">li</span><span class="kwrd">></span>@Html.Raw(tweet)<span class="kwrd"></</span><span class="html">li</span><span class="kwrd">></span><br /> }<br /><span class="kwrd"></</span><span class="html">ul</span><span class="kwrd">></span></pre><br /><br />Then, in my Master Page:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> @{Html.RenderPartial("TweetViewPartial", (object)ViewBag.MasterPageModel);}</pre><br /><br />Make sure to cast it to an object, because if not, .Net will complain that it doesn't have an overload that takes dynamic, since the ViewBag is dynamic. <br /><br />When you put it all together, we get this:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/2037392_master-page-model.jpg" style="width:879px;height:384px;"/><br /><br />The only tricky bit here, is to unit test this so that we can make sure we never accidentally mess up our DependencyResolver and no longer setting the MasterPageModel property. The hard part about this particular unit test, is that we need a UnityContainer. The problem is, we want to mock a ControllerBase, and an IMasterPageDataRetriever. Now remember, when mocking objects, the Mocking framework (in this case I'll be using Moq) creates Proxy objects with no types at runtime. For one reason or another, Unity doesn't play nice with Proxy types, so therefore, we're stuck using our own implementation of IUnityContainer. It's not bad because there's really only two things we need to give implementations for:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> TestContainer : IUnityContainer<br /> {<br /> <span class="kwrd">private</span> <span class="kwrd">readonly</span> IMasterPageDataRetriever _masterPageDataRetriever;<br /> <span class="kwrd">private</span> <span class="kwrd">readonly</span> ControllerBase _controllerBase;<br /><br /> <span class="kwrd">public</span> TestContainer(IMasterPageDataRetriever masterPageDataRetriever, ControllerBase controllerBase)<br /> {<br /> _masterPageDataRetriever = masterPageDataRetriever;<br /> _controllerBase = controllerBase;<br /> }<br /><br /> <span class="kwrd">public</span> IUnityContainer AddExtension(UnityContainerExtension extension)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">object</span> BuildUp(Type t, <span class="kwrd">object</span> existing, <span class="kwrd">string</span> name, <span class="kwrd">params</span> ResolverOverride[] resolverOverrides)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">object</span> Configure(Type configurationInterface)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /><br /> <span class="kwrd">public</span> IUnityContainer CreateChildContainer()<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /><br /> <span class="kwrd">public</span> IUnityContainer Parent<br /> {<br /> get<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> IUnityContainer RegisterInstance(Type t, <span class="kwrd">string</span> name, <span class="kwrd">object</span> instance, LifetimeManager lifetime)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /><br /> <span class="kwrd">public</span> IUnityContainer RegisterType(Type from, Type to, <span class="kwrd">string</span> name, LifetimeManager lifetimeManager, <span class="kwrd">params</span> InjectionMember[] injectionMembers)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /><br /> <span class="kwrd">public</span> IEnumerable<ContainerRegistration> Registrations<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> Enumerable.Empty<ContainerRegistration>();<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> IUnityContainer RemoveAllExtensions()<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">object</span> Resolve(Type t, <span class="kwrd">string</span> name, <span class="kwrd">params</span> ResolverOverride[] resolverOverrides)<br /> {<br /> <span class="kwrd">if</span> (t == <span class="kwrd">typeof</span>(IMasterPageDataRetriever))<br /> {<br /> <span class="kwrd">return</span> _masterPageDataRetriever;<br /> }<br /> <span class="kwrd">if</span> ((<span class="kwrd">typeof</span>(ControllerBase)).IsAssignableFrom(t))<br /> {<br /> <span class="kwrd">return</span> _controllerBase;<br /> }<br /><br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> InvalidOperationException();<br /> }<br /><br /> <span class="kwrd">public</span> IEnumerable<<span class="kwrd">object</span>> ResolveAll(Type t, <span class="kwrd">params</span> ResolverOverride[] resolverOverrides)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> Teardown(<span class="kwrd">object</span> o)<br /> {<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> Dispose()<br /> {<br /> }<br /> }</pre><br /><br />Basically, we take in an instance of an IMasterPageDataRetriever, and a ControllerBase. In the resolve method, we just pass the correct one back, based on what's being asked from it. Here's the actual test (I'm using NUnit, again, NuGet is awesome for adding all these references!!)<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> [TestFixture]<br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Tests<br /> {<br /> [Test]<br /> <span class="kwrd">public</span> <span class="kwrd">void</span> TestMasterPageDataGetsSetByDependencyResolver()<br /> {<br /> <span class="kwrd">const</span> <span class="kwrd">string</span> testData = <span class="str">"Test Data"</span>;<br /><br /> var masterDataRetrieverMoq = <span class="kwrd">new</span> Mock<IMasterPageDataRetriever>();<br /> masterDataRetrieverMoq.Setup(m => m.GetMasterPageData()).Returns(() => testData);<br /> var masterDataRetireverObject = masterDataRetrieverMoq.Object;<br /><br /> var controllerMoq = <span class="kwrd">new</span> Mock<ControllerBase>();<br /> var controllerObject = controllerMoq.Object;<br /> var unityDependencyResolver = <span class="kwrd">new</span> UnityDependencyResolver(<span class="kwrd">new</span> TestContainer(masterDataRetireverObject, controllerObject));<br /> var result = unityDependencyResolver.GetService(controllerObject.GetType()) <span class="kwrd">as</span> ControllerBase;<br /><br /> Assert.AreEqual(result.ViewBag.MasterPageModel, testData);<br /> }<br /> }</pre><br /><br />Here, we're mocking out the IMasterPageDataRetriever, and making it return a string "Test Data". After registering that instance with our fake container, and then calling GetService on the UnityDependencyResolver, the Mocked ControllerBase ViewBag should have the "Test Data" set.<br /><br />Like I said in the beginning, this is far from the only way of doing it, it's just that I like this approach because you don't need to force your ViewModels from inheriting some base view model, you don't need to have a custom ControllerBase, you just need to massage your Dependency Injection code a bit, and then forget it's ever there. Also, as I've shown, it's still testable, which is always a good thing! Enjoy!A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com5tag:blogger.com,1999:blog-5611706923356552090.post-37661783161570046812010-05-23T01:01:00.005-04:002010-05-23T01:32:09.704-04:00INotifyPropertyChanged without the magic strings. A neat alternative....<span style="font-weight:bold;">Source Code</span>: <a href="http://www.box.net/shared/5kjn0tr90c">http://www.box.net/shared/5kjn0tr90c</a><br /><br />A while back <a href="http://crazorsharp.blogspot.com/2009/06/inotifypropertychanged-how-to-and-when.html">I blogged</a> about the INotifyPropertyChanged interface, and how to properly use it. Back in that post I noted at the end that using magic strings to specify which property has changed, has its drawbacks. A little refresher as to what I'm talking about; this is the common way that the INotifyPropertyChanged interface is used:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> MyClass : INotifyPropertyChanged<br /> {<br /> <span class="kwrd">private</span> <span class="kwrd">int</span> myInt;<br /><br /> <span class="kwrd">public</span> <span class="kwrd">int</span> MyInt<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.myInt;<br /> }<br /> set<br /> {<br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.myInt != <span class="kwrd">value</span>)<br /> {<br /> <span class="kwrd">this</span>.myInt = <span class="kwrd">value</span>;<br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.PropertyChanged != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">this</span>.PropertyChanged(<span class="kwrd">this</span>, <span class="kwrd">new</span> PropertyChangedEventArgs(<span class="str">"MyInt"</span>));<br /> }<br /> }<br /> }<br /> }<br /> <br /> <span class="kwrd">public</span> <span class="kwrd">event</span> PropertyChangedEventHandler PropertyChanged;<br /> }</pre><br /><br />while this does work, the problem is immediately obvious. Actually hard-coding the "MyInt" when the event gets raised is very fragile and extremely error prone. If someone changes the property name for example, and forgets to update the "magic string" in the event-raising code, all your binding goes straight to hell.<br /><br />Since joining <a href="http://lab49.com/">Lab49</a> I've been using WPF a lot, and the INotifyPropertyChanged interface is used all throughout WPF. Therefore, I've started using a new approach, and while it does require more plumbing code, I think it adds a lot of value since we get rid of the magic strings, and get compile time checking. Here's what I came up with:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> NotifyProperty<TContaining, TProperty><br /> {<br /> <span class="preproc">#region</span> Members<br /><br /> <span class="kwrd">private</span> <span class="kwrd">string</span> propertyName;<br /> <span class="kwrd">private</span> TProperty backingStore;<br /> <span class="kwrd">private</span> Comparison<TProperty> comparer;<br /><br /> <span class="preproc">#endregion</span><br /><br /> <span class="preproc">#region</span> Constructors<br /><br /> <span class="kwrd">public</span> NotifyProperty(Expression<Func<TContaining, TProperty>> expression)<br /> : <span class="kwrd">this</span>(expression, Comparer<TProperty>.Default.ToComparison())<br /> {<br /><br /> }<br /><br /> <span class="kwrd">public</span> NotifyProperty(Expression<Func<TContaining, TProperty>> expression, IComparer<TProperty> comparer)<br /> : <span class="kwrd">this</span>(expression, comparer.ToComparison())<br /> {<br /><br /> }<br /><br /> <span class="kwrd">public</span> NotifyProperty(Expression<Func<TContaining, TProperty>> expression, Comparison<TProperty> comparer)<br /> {<br /> <span class="kwrd">if</span> (expression == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentNullException(<span class="str">"expression"</span>);<br /> }<br /><br /> <span class="kwrd">if</span> (comparer == <span class="kwrd">null</span>)<br /> {<br /> comparer = Comparer<TProperty>.Default.ToComparison();<br /> }<br /> <br /> <span class="kwrd">this</span>.comparer = comparer;<br /><br /> var memberExpression = expression.Body <span class="kwrd">as</span> MemberExpression;<br /> <span class="kwrd">if</span> (memberExpression == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> InvalidOperationException(<span class="str">"Only properties can be used."</span>);<br /> }<br /><br /> <span class="kwrd">this</span>.propertyName = memberExpression.Member.Name;<br /> }<br /><br /> <span class="preproc">#endregion</span><br /><br /> <span class="preproc">#region</span> Methods<br /><br /> <span class="kwrd">public</span> TProperty GetValue()<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.backingStore;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> SetValue(TContaining containing, TProperty <span class="kwrd">value</span>, PropertyChangedEventHandler propertyChanged)<br /> {<br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.IsNewValue(<span class="kwrd">value</span>))<br /> {<br /> <span class="kwrd">this</span>.backingStore = <span class="kwrd">value</span>;<br /> <span class="kwrd">this</span>.RaisePropertyChanged(containing, propertyChanged);<br /> }<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> RaisePropertyChanged(TContaining containing, PropertyChangedEventHandler propertyChanged)<br /> {<br /> <span class="kwrd">if</span> (propertyChanged != <span class="kwrd">null</span>)<br /> {<br /> propertyChanged(containing, <span class="kwrd">new</span> PropertyChangedEventArgs(<span class="kwrd">this</span>.propertyName));<br /> }<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">bool</span> IsNewValue(TProperty newValue)<br /> {<br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.comparer == <span class="kwrd">null</span>) { <span class="kwrd">return</span> <span class="kwrd">true</span>; }<br /><br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.comparer(<span class="kwrd">this</span>.backingStore, newValue) != 0;<br /> }<br /><br /> <span class="preproc">#endregion</span><br /> }</pre><br /><br />And this is how you would use it:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> MyClass : INotifyPropertyChanged<br /> {<br /> <span class="kwrd">private</span> NotifyProperty<MyClass,<span class="kwrd">int</span>> myInt;<br /><br /> <span class="kwrd">public</span> MyClass()<br /> {<br /> <span class="kwrd">this</span>.myInt = <span class="kwrd">new</span> NotifyProperty<MyClass, <span class="kwrd">int</span>>(m => m.MyInt);<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">int</span> MyInt<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.myInt.GetValue();<br /> }<br /> set<br /> {<br /> <span class="kwrd">this</span>.myInt.SetValue(<span class="kwrd">this</span>, <span class="kwrd">value</span>, <span class="kwrd">this</span>.PropertyChanged);<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">event</span> PropertyChangedEventHandler PropertyChanged;<br /> }</pre><br /><br />Using <a href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx">Expressions</a>, we can take advantage of the fact that we can pass a Func to the constructor of our NotifyProperty class, and still get <span style="font-weight:bold;">compile </span>time checking. <br /><br />I'll briefly run through the code and explain what's happening. The first and most important part to understand is the Expression stuff. While I'm no expert on Expressions, I've used them in the past for this purpose. The compiler allows you to pass a Func wherever an Expression of type Func is expected. Under the covers, the compiler converts it from a Func to an Expression, but at the same time, it extracts some important Metadata about the Func, <span style="font-weight:bold;">including the name</span>, which we can then grab through the Name property.<br /><br />The other piece here is all the Comparison stuff. This isn't really needed, but it just follows the same pattern used when raising the PropertyChanged event. You only want to raise the event if the underlying value actually changed. Therefore, I fleshed it out and overloaded the constructors to allow for different methods of comparison to be passed in. To make that possible, I added this extension method:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> Comparison<T> ToComparison<T>(<span class="kwrd">this</span> IComparer<T> comparer)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">new</span> Comparison<T>(comparer.Compare);<br /> }</pre><br /><br />This just converts an instance of IComparer<T> to an instance of Comparison so that you can either pass in an interface implementation or a delegate. <br /><br />Now, like I said earlier, this does require more plumbing code and writing out a property does look more cumbersome. I'll admit that it's a tradeoff, but I personally try to avoid magic strings like the plague, which is why I think this is in fact a much better approach. I added a link to the top of the page with the source code. It contains the class along with some unit tests. Drop me a line and let me know what you think. Until then, Good luck and Happy coding!A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com2tag:blogger.com,1999:blog-5611706923356552090.post-19573422459862991972010-01-24T01:25:00.020-05:002011-08-04T12:45:18.835-04:00Full Text Search using Solr / Lucene and C# / .NET. End to end tutorial on using these technologies with SolrNet.<span style="font-weight:bold;"><a href="http://www.box.net/shared/efcss6fnjp">Link to source code and other goodies discussed here.</a></span><br /><br /><span style="font-weight:bold;">UPDATE: <a href="http://www.box.net/shared/vtbod3rub6ibvof91xut">TextFileHarvester for SQL 2008 can now be found here.</a></span><br /><br />I think the first thing to answer is, What is Solr? I'll let Solr explain itself:<br /><blockquote><br />Solr is the popular, blazing fast open source enterprise search platform from the Apache Lucene project. Its major features include powerful full-text search, hit highlighting, faceted search, dynamic clustering, database integration, and rich document (e.g., Word, PDF) handling. Solr is highly scalable, providing distributed search and index replication, and it powers the search and navigation features of many of the world's largest internet sites.<br /><br />Solr is written in Java and runs as a standalone full-text search server within a servlet container such as Tomcat. Solr uses the Lucene Java search library at its core for full-text indexing and search, and has REST-like HTTP/XML and JSON APIs that make it easy to use from virtually any programming language. Solr's powerful external configuration allows it to be tailored to almost any type of application without Java coding, and it has an extensive plugin architecture when more advanced customization is required. </blockquote><br /><br />Simply put, Lucene is an open-source Java library that does full text searching. In other words, if you want to provide searching beyond the simple "sql like query" you'll need full text search. Now Lucene does just that, but firstly, it's written in Java (there is a .Net version called <a href="http://incubator.apache.org/lucene.net/">Lucene.net</a> but frankly they're way behind the original Java project, and I don't know how active that community is.) Secondly, it's just a library, so you'd need to create your own search engine around it. That's where Solr comes in. Solr is a Java web based application that functions as a Search engine (using Lucene under the covers). The nice thing about it is that it has a simple Web Service API that's XML based which means, it can be used from C# (or any other language for that matter). <br /><br />The point of this tutorial is to provide a simple walkthrough to getting Solr up and running to index and search some documents using C#. I work in Computer Forensics / E-Discovery where being able to search and filter documents is vital. I learned alot on the job, and felt that there wasn't really one good end to end tutorial aimed at C# developers, so I hope someone will find at least some of this information useful.<br /><br />Here's how this will work. First, I'll walk you through getting Tomcat up and running. Then, I'll demonstrate how to install Solr. Next, I'll have you download a little utility I wrote which basically creates a database, and downloads a whole bunch of text files off the net. Finally, we'll write some C# code to index and search those text files.<br /><br /><span style="font-weight:bold;">Part 1: Installing Tomcat:</span><br /><br />From their website: <br /><br /><blockquote>Apache Tomcat is an open source software implementation of the Java Servlet and JavaServer Pages technologies. The Java Servlet and JavaServer Pages specifications are developed under the Java Community Process.</blockquote><br /><br />Since Solr is a Java web app, we need a server to host the Java Servlet (that's basically a Java web app). First, you'll need to make sure Java is installed on your machine. You can go to this site which will tell you whether or not it's installed: <a href="http://www.java.com/en/download/help/testvm.xml">http://www.java.com/en/download/help/testvm.xml</a> If you see this:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/1138473_java-installed.jpg"><br /><br />then you have Java installed. Otherwise, head on over to <a href="http://tinyurl.com/yexjbsd">this link</a>, and grab the latest version of the JRE (Java Runtime Environment.)<br /><br />The next step is to install Tomcat. You can grab it here: <a href="http://apache.cyberuse.com/tomcat/tomcat-6/v6.0.24/bin/apache-tomcat-6.0.24.exe">http://apache.cyberuse.com/tomcat/tomcat-6/v6.0.24/bin/apache-tomcat-6.0.24.exe</a> That's the windows Installer version. Run the install and click Next until you get to this page:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/1138474_tomcat-install.jpg"><br /><br />You can put any port number into the Port text box (the default is 8080). I put 8983 as that's the default you'll see in all Solr examples on the net. You can choose any port you'd like it doesn't really matter. Just remember which port you choose as that'll always be part of the URL when connecting to Solr. In all my examples here, I'll be using 8983.<br /><br />On the next screen, it'll try to find the location of the JRE on your system:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/1138475_tomcat-jre.jpg"><br /><br />It should find it automatically, but if it doesn't make sure to point it to directory where Java was installed on your system. Click next and Tomcat will install. <br /><br />Once you finish the installation, tomcat will start and you'll see this:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/1138476_tomcat-startup.jpg"><br /><br />(If you don't see that, either look at your Windows Taskbar in the bottom right for the Tomcat icon, or go to Start-> Programs -> Appache Tomcat 6.0 -> Configure Tomcat)<br /><br />Click on the Start button and watch Tomcat startup. Above the Start button you should now see "Serive Status: Started. <span style="font-weight:bold;">If it does not, here's what you need to do. Go to Program Files\Java\jre6\bin and locate the file called msvcr71.dll. Copy that file and paste it into C:\Windows\system. Now try starting Tomcat up again, and now it should work. Don't ask me why, but after breaking my head a while back on one of my test machines, I found the answer on Google.</span><br /><br />Once Tomcat is started, open a web browser and navigate to: <a href="http://localhost:8983">http://localhost:8983</a> (remember, if you used a different port during installation, use that one instead). You should be greeted with this beautiful page:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/1138477_tomcat-welcome.jpg"><br /><br />If you don't see that page, please refer to <a href="http://wiki.apache.org/tomcat/FAQ">Tomcat's FAQ.</a><br /><br /><span style="font-weight:bold;">Step 2: Installing Solr</span><br /><br />The next step in this process is to install the Solr web application. First, let's shut down Tomcat. (Click Start-> Programs -> Appache Tomcat 6.0 -> Configure Tomcat and click on the Stop button.) Next, we'll need to download Solr. As of the time of this blog post, the latest version of Solr is 1.4 so let's download and install that one. Head on over to this page and choose the mirror of your choice: <a href="http://www.apache.org/dyn/closer.cgi/lucene/solr/1.4.0">http://www.apache.org/dyn/closer.cgi/lucene/solr/1.4.0</a> Once you click on one of the mirror links, you'll be taken to a page where you can choose the different formats to download. Download this one:<br /><br />apache-solr-1.4.0.zip <br /><br />Once that's downloaded, unzip the file and locate the folder "$\apache-solr-1.4.0\dist". In there you'll see a file "apache-solr-1.4.0.war"; war files are basically zipped up files that contain all of the necessary binaries for the servlet container (Tomcat) to run the webapp. Copy that file and past it to: "$\Program Files\Apache Software Foundation\Tomcat 6.0\webapps" <span style="font-weight:bold;">Rename the file to solr.war because that will be the name of the URL to access Solr.</span> <br /><br />Next, we need to create the "Solr Home". The Solr home is basically a folder where Tomcat will look for all the relevant Solr configurations, as well as where the actual index files will be stored. Go back to the unzipped solr package, and locate the folder: "$\apache-solr-1.4.0\example\solr". Copy the contents of that directory (should be a bin folder, a conf folder and a readme.txt) and place it under your root directory, under a folder named Solr (e.g. C:\Solr). Note: You can place it anywhere on your hard drive, doesn't have to be under the root, but wherever you place it, make sure to remember the full path. For now, don't worry about what exactly you're doing, I'll explain more later. <br /><br />Next next step is to tell Tomcat where the Solr Home folder is. Open Tomcat's configuration window again, and go to the Java tab. Locate the Java Options text box, and enter this line at the end of all the other stuff that's already there:<br /><br /><span style="font-weight:bold;">-Dsolr.solr.home=c:\solr</span><br /><br />(If you chose a different Home Folder, place that path instead.)<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/1138481_tomcat-java.jpg"><br /><br />Now go back to the General tab, and click Start. Once Tomcat starts up, open your browser and navigate to:<br /><br /><a href="http://localhost:8983/solr/">http://localhost:8983/solr/</a><br /><br />You should be greeted with this page:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/1138482_solr-welcome.jpg"><br /><br />Click on the Solr Admin link and you'll see this page:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/1138483_solr-main.jpg"><br /><br />In the Query String box, replace the word solr with this: *:* (this is the lucene syntax for "select all") and click Search. You should now see a page of results in XML format. At this point we haven't indexed anything, so you won't see any results, but Congratulations, you've set up Solr!<br /><br /><span style="font-weight:bold;">Step 2.1: Configuring Solr</span><br /><br />In order to move on to Solr Configurations, it's important to take a minute and explore how Lucene works. I'm no expert, and if you want a deeper understanding, use Google, but I will mention a few key points. <br /><br />The first step to getting documents search-able is to index them. I'm sure you've heard that term before, but what exactly does that mean? At the heart of indexing are two concepts known as Tokenizing, and Filtering. The idea is, you use these tokenizers (that have custom analyzers) and filters to analyze the data and store them in a custom file structure known as an index. I think <a href="http://www.darksleep.com/lucene/">this page does a great job</a> of explaining it:<br /><blockquote><br />The analyzer's job is to take apart a string of text and give you back a stream of tokens. The tokens are presumably usually words from the text content of the string, and that's what gets stored (along with the location and other details) in the index.<br /><br />Each analyzer includes one or more tokenizers and may include filters. The tokenizers take care of the actual rules for where to break the text up into words (typically whitespace). The filters do any post-tokenizing work on the tokens (typically dropping out punctuation and commonly occurring words like "the", "an", "a", etc).</blockquote><br /><br />So you feed Lucene the data, it analyzes it and tokenizes it, at which point it is now search-able. Then, when you submit a query, it uses the <span style="font-weight:bold;">same tokenizers and filters</span> to parse the query, and return the results. Why is this relevant? Well, because different data will be tokenized differently. For most text you'll use a WhitespaceTokenizer which splits on white spaces, and tokenizes the words and generally ignoring special characters. For integers or dates for example, you obviously don't want that kind of tokenizer. You want to be able to specify that this is an int field, and be sorted as an int for example.<br /><br />That's where the Solr config file comes in. You specify all the fields that you want to index, as well as which tokenizers and filters to use for those fields. If you've been following along with this tutorial, you'll find the config file(s) under $/Solr/Conf. There will be many files there, but we won't concern ourselves with all of them. For now we'll focus on schema.xml. The other one I'd like to mention is the solrconfig.xml file which basically are settings for solr itself (how often to commit the index, how much ram to use while indexing etc...). The great thing about the example files is that there's very very detailed documentation in the XML files.<br /><br />For this tutorial, I'll be using text files that can be downloaded for free from <a href="http://www.textfiles.com">http://www.textfiles.com</a>. There you'll find thousands of text files from the early days of the net. I'll provide a link further down to a simple application that I wrote that scrapes the site, downloads as many files as you specify, and creates a database for you with the relevant information. For now though, I'd like to show you the config file needed to index these documents. We'll be indexing these fields:<br /><br /><ul><br /><li>fileid</li><br /><li>doctext</li><br /><li>title</li><br /><li>datecreated</li><br /></ul><br /><br />Here's the schema.xml file needed:<br /><div style="overflow:auto"><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd"><?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="UTF-8"</span> ?<span class="kwrd">></span> <br /> <span class="kwrd"><</span><span class="html">schema</span> <span class="attr">name</span><span class="kwrd">="example"</span> <span class="attr">version</span><span class="kwrd">="1.2"</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">types</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">fieldType</span> <span class="attr">name</span><span class="kwrd">="string"</span> <span class="attr">class</span><span class="kwrd">="solr.StrField"</span> <span class="attr">sortMissingLast</span><span class="kwrd">="true"</span> <span class="attr">omitNorms</span><span class="kwrd">="true"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">fieldType</span> <span class="attr">name</span><span class="kwrd">="int"</span> <span class="attr">class</span><span class="kwrd">="solr.TrieIntField"</span> <span class="attr">precisionStep</span><span class="kwrd">="0"</span> <span class="attr">omitNorms</span><span class="kwrd">="true"</span> <span class="attr">positionIncrementGap</span><span class="kwrd">="0"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">fieldType</span> <span class="attr">name</span><span class="kwrd">="date"</span> <span class="attr">class</span><span class="kwrd">="solr.TrieDateField"</span> <span class="attr">omitNorms</span><span class="kwrd">="true"</span> <span class="attr">precisionStep</span><span class="kwrd">="0"</span> <span class="attr">positionIncrementGap</span><span class="kwrd">="0"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">fieldType</span> <span class="attr">name</span><span class="kwrd">="text"</span> <span class="attr">class</span><span class="kwrd">="solr.TextField"</span> <span class="attr">positionIncrementGap</span><span class="kwrd">="100"</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">analyzer</span> <span class="attr">type</span><span class="kwrd">="index"</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">tokenizer</span> <span class="attr">class</span><span class="kwrd">="solr.WhitespaceTokenizerFactory"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">filter</span> <span class="attr">class</span><span class="kwrd">="solr.StopFilterFactory"</span> <span class="attr">ignoreCase</span><span class="kwrd">="true"</span> <span class="attr">words</span><span class="kwrd">="stopwords.txt"</span> <span class="attr">enablePositionIncrements</span><span class="kwrd">="true"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">filter</span> <span class="attr">class</span><span class="kwrd">="solr.WordDelimiterFilterFactory"</span> <span class="attr">generateWordParts</span><span class="kwrd">="1"</span> <span class="attr">generateNumberParts</span><span class="kwrd">="1"</span> <span class="attr">catenateWords</span><span class="kwrd">="1"</span> <span class="attr">catenateNumbers</span><span class="kwrd">="1"</span> <span class="attr">catenateAll</span><span class="kwrd">="0"</span> <span class="attr">splitOnCaseChange</span><span class="kwrd">="1"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">filter</span> <span class="attr">class</span><span class="kwrd">="solr.LowerCaseFilterFactory"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">filter</span> <span class="attr">class</span><span class="kwrd">="solr.SnowballPorterFilterFactory"</span> <span class="attr">language</span><span class="kwrd">="English"</span> <span class="attr">protected</span><span class="kwrd">="protwords.txt"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"></</span><span class="html">analyzer</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">analyzer</span> <span class="attr">type</span><span class="kwrd">="query"</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">tokenizer</span> <span class="attr">class</span><span class="kwrd">="solr.WhitespaceTokenizerFactory"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">filter</span> <span class="attr">class</span><span class="kwrd">="solr.SynonymFilterFactory"</span> <span class="attr">synonyms</span><span class="kwrd">="synonyms.txt"</span> <span class="attr">ignoreCase</span><span class="kwrd">="true"</span> <span class="attr">expand</span><span class="kwrd">="true"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">filter</span> <span class="attr">class</span><span class="kwrd">="solr.StopFilterFactory"</span> <span class="attr">ignoreCase</span><span class="kwrd">="true"</span> <span class="attr">words</span><span class="kwrd">="stopwords.txt"</span> <span class="attr">enablePositionIncrements</span><span class="kwrd">="true"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">filter</span> <span class="attr">class</span><span class="kwrd">="solr.WordDelimiterFilterFactory"</span> <span class="attr">generateWordParts</span><span class="kwrd">="1"</span> <span class="attr">generateNumberParts</span><span class="kwrd">="1"</span> <span class="attr">catenateWords</span><span class="kwrd">="0"</span> <span class="attr">catenateNumbers</span><span class="kwrd">="0"</span> <span class="attr">catenateAll</span><span class="kwrd">="0"</span> <span class="attr">splitOnCaseChange</span><span class="kwrd">="1"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">filter</span> <span class="attr">class</span><span class="kwrd">="solr.LowerCaseFilterFactory"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">filter</span> <span class="attr">class</span><span class="kwrd">="solr.SnowballPorterFilterFactory"</span> <span class="attr">language</span><span class="kwrd">="English"</span> <span class="attr">protected</span><span class="kwrd">="protwords.txt"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"></</span><span class="html">analyzer</span><span class="kwrd">></span><br /> <span class="kwrd"></</span><span class="html">fieldType</span><span class="kwrd">></span><br /> <span class="kwrd"></</span><span class="html">types</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">fields</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">field</span> <span class="attr">name</span><span class="kwrd">="fileid"</span> <span class="attr">type</span><span class="kwrd">="int"</span> <span class="attr">indexed</span><span class="kwrd">="true"</span> <span class="attr">stored</span><span class="kwrd">="true"</span> <span class="attr">required</span><span class="kwrd">="true"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">field</span> <span class="attr">name</span><span class="kwrd">="doctext"</span> <span class="attr">type</span><span class="kwrd">="text"</span> <span class="attr">indexed</span><span class="kwrd">="true"</span> <span class="attr">stored</span><span class="kwrd">="false"</span> <span class="attr">required</span><span class="kwrd">="false"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">field</span> <span class="attr">name</span><span class="kwrd">="title"</span> <span class="attr">type</span><span class="kwrd">="text"</span> <span class="attr">indexed</span><span class="kwrd">="true"</span> <span class="attr">stored</span><span class="kwrd">="false"</span> <span class="attr">required</span><span class="kwrd">="false"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"><</span><span class="html">field</span> <span class="attr">name</span><span class="kwrd">="datecreated"</span> <span class="attr">type</span><span class="kwrd">="date"</span> <span class="attr">indexed</span><span class="kwrd">="true"</span> <span class="attr">stored</span><span class="kwrd">="false"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"></</span><span class="html">fields</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">uniqueKey</span><span class="kwrd">></span>fileid<span class="kwrd"></</span><span class="html">uniqueKey</span><span class="kwrd">></span> <br /> <span class="kwrd"><</span><span class="html">defaultSearchField</span><span class="kwrd">></span>doctext<span class="kwrd"></</span><span class="html">defaultSearchField</span><span class="kwrd">></span> <br /> <span class="kwrd"><</span><span class="html">solrQueryParser</span> <span class="attr">defaultOperator</span><span class="kwrd">="OR"</span> <span class="kwrd">/></span> <br /> <span class="kwrd"></</span><span class="html">schema</span><span class="kwrd">></span></pre></div><br /><br />As you can see, the XML is pretty straight forward. I'd like to touch on two of the attributes in the field tag: <br /><br />The first one is "stored". A lot of people make this mistake the first time they mess with Lucene, and they stored everything in the index. I'd like to stress this point really really strongly.<span style="font-weight:bold;"> An index is NOT a data storeage mechanism. It's not intended for that, it's not optimized for that.</span> That's what Databases are for. What I mean by that is, the text you send to get indexed, gets tokenized and totally bastardized. There's no way to re-construct the original document. So what Lucene allows you to do, is store the text as is in the index as well for later retrieval. That's OK for small index's or small fields. However when you get to larger indexes or larger fields, your performance will suffer noticeably. What's most commonly done, is you index everything you need, however you only STORE the primary key (e.g. fileid). When you retrieve the items from the index during search, you get the primary key field, and then you query your database which IS meant for data storage, and get the rest of the fields you need. That's the approach I'll be taking here.<br /><br />The other field I'd like to point out, is the "type" field. This tells Lucene, which kind of field this one will be, and based on the fieldtypes specified earlier, it uses the correct tokenizer.<br /><br />There's also one change I think is worth making in the solconfig.xml. Not too far down in the solrconfig.xml file you'll see this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="rem"><!-- Used to specify an alternate directory to hold all index data</span><br /><span class="rem"> other than the default ./data under the Solr home.</span><br /><span class="rem"> If replication is in use, this should match the replication configuration.--></span><br /> <span class="kwrd"><</span><span class="html">dataDir</span><span class="kwrd">></span>${solr.data.dir:./solr/data}<span class="kwrd"></</span><span class="html">dataDir</span><span class="kwrd">></span></pre><br /><br />For some reason the example defaults to putting the index file in the same directory as the Tomcat server. Just comment out that line:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="rem"><!-- Used to specify an alternate directory to hold all index data</span><br /><span class="rem"> other than the default ./data under the Solr home.</span><br /><span class="rem"> If replication is in use, this should match the replication configuration.</span><br /><span class="rem"> <dataDir>${solr.data.dir:./solr/data}</dataDir>--></span></pre><br /><br />we'll use the default "Solr Home" folder ($\solr\data\index) to store the index files.<br /><br />At this point, in your /solr/conf folder, you should have these files: (delete all the other ones)<br /><br /><ul><br /><li>schema.xml (copy and paste the xml from above)</li><br /><li>elevate.xml</li><br /><li>protwords.txt</li><br /><li>solrconfig.xml</li><br /><li>stopwords.txt</li><br /><li>synonyms.txt</li><br /></ul><br /><br /><span style="font-weight:bold;">Part 3: Downloading Some Text Files</span><br /><br />OK, now we have most of our environment set up, it's time to get some files! I created a simple application, that connects to <a href="http://www.textfiles.com">http://www.textfiles.com</a> and downloads some files. It then creates a database and adds a record for each file downloaded. You can download it here:<br /><br />For SQL 2005: <a href="http://www.box.net/shared/du4zac9vaa">http://www.box.net/shared/du4zac9vaa</a><br /><br />For SQL 2008: <a href="http://www.box.net/shared/vtbod3rub6ibvof91xut">http://www.box.net/shared/vtbod3rub6ibvof91xut</a><br /><br />Here's how you use it:<br /><br />TextFileHarvester.exe "ALEX\SQLEXPRESS" "TextFilesDatabase" "C:\MyTextFiles" 1000<br /><br />First parameter is the Sql Server name. The second one is the Database name to create. The third one is the location where to store the text files on disk, and the last parameter is how many files to download.<br /><br />Once that's done, you should have a database that looks something like this:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/1141523_db-shot.jpg"><br /><br />Just as a side point, the Dates are made up. They're just random dates between 1995 - 2005.<br /><br />You should also have a directory (in the location you specified to the TextFileHarvester app) with many text files in them.<br /><br /><span style="font-weight:bold;">Part 4: Writing Some Code!!</span><br /><br />Now comes the fun part. Earlier I mentioned that Solr was basically a Webservice that you can interact with using http and sending XML. You can do all of the work manually and create the XML by hand, but there's an awesome library out there that already does this. The library is open source and called <a href="http://code.google.com/p/solrnet/">SolrNet</a>. Head on over there and download the dll's. (There's actually another library called <a href="http://solrsharp.codeplex.com/">SolrSharp</a> but that's much older, and not as up to date as SolrNet. Also, in my opinion, SolrNet is much easier to use.)<br /><br />Ok, now that we have the SolrNet dll's, we can create a simple application to Index them. We'll keep it simple, and do this: Connect to the database, get all of the files in one shot, connect to Solr and send them all to be indexed. <br /><br />The way you send stuff to Solr using SolrNet is by having a class that holds your data, and then you add an attribute to each property that maps to a property in the index. Let me explain with code:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> TextFile<br /> {<br /> <span class="preproc">#region</span> Members<br /><br /> <span class="kwrd">private</span> <span class="kwrd">string</span> documentText;<br /><br /> <span class="preproc">#endregion</span><br /><br /> [SolrUniqueKey(<span class="str">"fileid"</span>)]<br /> <span class="kwrd">public</span> <span class="kwrd">int</span> FileID { get; <span class="kwrd">internal</span> set; }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">string</span> FileLocation { get; <span class="kwrd">internal</span> set; }<br /><br /> [SolrField(<span class="str">"doctext"</span>)]<br /> <span class="kwrd">public</span> <span class="kwrd">string</span> DocumentText<br /> {<br /> get<br /> {<br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.documentText == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">this</span>.documentText = File.ReadAllText(FileLocation);<br /> }<br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.documentText;<br /> }<br /> <br /> }<br /><br /> [SolrField(<span class="str">"title"</span>)]<br /> <span class="kwrd">public</span> <span class="kwrd">string</span> Title { get; <span class="kwrd">internal</span> set; }<br /><br /> [SolrField(<span class="str">"datecreated"</span>)]<br /> <span class="kwrd">public</span> DateTime? DateCreated { get; <span class="kwrd">internal</span> set; }<br /> }<br /></pre><br /><br />You add the SolrField attribute (or the SolrUniqueKey for the index primary key field) and provide the name for that field in the index. I made the DocumentText property be lazy loaded so we don't hit the file system for all file's text in one shot (there should probably be more error handling there, but hey, this is just a demo...). <br /><br />SolrNet will require a collection of these objects, and it will then send that off to the index. The next step therefore, is to write some code to populate these objects. We can use Linq to Sql, or whatever you want to connect to the database and populate these objects. I wrote some (very) basic ADO.NET code to do this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">internal</span> <span class="kwrd">class</span> TextFileRepository<br /> {<br /> <span class="preproc">#region</span> Members<br /><br /> <span class="kwrd">private</span> <span class="kwrd">string</span> connectionString;<br /><br /> <span class="preproc">#endregion</span><br /><br /> <span class="preproc">#region</span> Constructors<br /><br /> <span class="kwrd">public</span> TextFileRepository(<span class="kwrd">string</span> connectionString)<br /> {<br /> <span class="kwrd">this</span>.connectionString = connectionString;<br /> }<br /><br /> <span class="preproc">#endregion</span><br /><br /> <span class="preproc">#region</span> Methods<br /><br /> <span class="kwrd">public</span> IEnumerable<TextFile> GetTextFiles()<br /> {<br /> <span class="kwrd">return</span> ExecuteSql(<span class="str">"SELECT * FROM FILES"</span>);<br /> }<br /><br /> <span class="kwrd">public</span> IEnumerable<TextFile> GetTextFiles(IEnumerable<<span class="kwrd">int</span>> fileIds)<br /> {<br /> <span class="kwrd">if</span> (!fileIds.Any()) { <span class="kwrd">yield</span> <span class="kwrd">break</span>; }<br /> <span class="kwrd">string</span> sql = String.Format(<span class="str">"SELECT * FROM FILES WHERE FILEID IN({0})"</span>, fileIds.ToDelimetedString());<br /> <span class="kwrd">foreach</span> (var item <span class="kwrd">in</span> ExecuteSql(sql))<br /> {<br /> <span class="kwrd">yield</span> <span class="kwrd">return</span> item;<br /> }<br /> }<br /><br /> <span class="kwrd">private</span> IEnumerable<TextFile> ExecuteSql(<span class="kwrd">string</span> sql)<br /> {<br /> <span class="kwrd">using</span> (SqlConnection connection = <span class="kwrd">new</span> SqlConnection(<span class="kwrd">this</span>.connectionString))<br /> <span class="kwrd">using</span> (SqlCommand command = connection.CreateCommand())<br /> {<br /> command.CommandText = sql;<br /> connection.Open();<br /> var reader = command.ExecuteReader();<br /> <span class="kwrd">while</span> (reader.Read())<br /> {<br /> <span class="kwrd">yield</span> <span class="kwrd">return</span> FromReader(reader);<br /> }<br /> }<br /> }<br /><br /> <span class="kwrd">private</span> TextFile FromReader(SqlDataReader reader)<br /> {<br /> var result = <span class="kwrd">new</span> TextFile();<br /> result.FileID = (<span class="kwrd">int</span>)reader[<span class="str">"FileID"</span>];<br /> result.Title = reader[<span class="str">"Title"</span>] <span class="kwrd">as</span> <span class="kwrd">string</span>;<br /> result.FileLocation = reader[<span class="str">"FileLocation"</span>] <span class="kwrd">as</span> <span class="kwrd">string</span>;<br /> var date = reader[<span class="str">"DateCreated"</span>];<br /> result.DateCreated = date == DBNull.Value ? (DateTime?)<span class="kwrd">null</span> : date <span class="kwrd">as</span> DateTime?;<br /><br /> <span class="kwrd">return</span> result;<br /> }<br /><br /> <span class="preproc">#endregion</span><br /> }<br /></pre><br /><br />Nothing fancy. If you look at the GetTextFiles method it's about as straight forward as they come. Just do a SELECT * and convert to the TextFile object. (You'll notice a GetTextFiles with a parameter, but that's used for Searching as I'll explain shortly.)<br /><br /><span style="font-weight:bold;">Part 4.1: Indexing the Files</span><br /><br />Now, we can write some code to Index these files:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> BasicIndexer<br /> {<br /> <span class="kwrd">private</span> <span class="kwrd">string</span> connectionString;<br /> <span class="kwrd">private</span> <span class="kwrd">string</span> solrUrl;<br /><br /> <span class="kwrd">public</span> BasicIndexer(<span class="kwrd">string</span> connectionString, <span class="kwrd">string</span> solrUrl)<br /> {<br /> <span class="kwrd">this</span>.connectionString = connectionString;<br /> <span class="kwrd">this</span>.solrUrl = solrUrl;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> IndexFiles()<br /> {<br /> Startup.Init<TextFile>(<span class="kwrd">this</span>.solrUrl);<br /> var solrWorker = ServiceLocator.Current.GetInstance<ISolrOperations<TextFile>>();<br /> var files = <span class="kwrd">new</span> TextFileRepository(<span class="kwrd">this</span>.connectionString).GetTextFiles();<br /> solrWorker.Add(files).Commit();<br /> }<br /> }</pre><br /><br />Pretty simple no? First, we need to call the Init method. Internally SolrNet uses IoC to handle the instantiation of the classes. Therefore, we can just use Microsoft.Practices.ServiceLocation from the Enterprise Library. (I'm not a huge fan of the Enterprise Library, but it's quick and easy for this example. Refer to the SolrNet documentation for better approaches using Castle Windsor.) Once we have the ISolrOperations, we can just call the Database to get all the files, and then call Add on the ISolrOperations. Once that's done, we just call Commit() and that's it!!<br /><br />Let's give it a whirl. Create a quick ConsoleApplication and call the BasicIndexer class:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Program<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)<br /> {<br /> <span class="kwrd">string</span> connectionString = <span class="str">""</span>;<br /> <span class="kwrd">string</span> solrUrl = <span class="str">""</span>;<br /><br /> BasicIndexer indexer = <span class="kwrd">new</span> BasicIndexer(connectionString, solrUrl);<br /> indexer.IndexFiles();<br /> }<br /> }</pre><br /><br />Fill in the blanks for your specific connection string, and your solr url (e.g. http://localhost:8983/solr). MAKE SURE YOU RESTART TOMCAT!! (Start -> Programs -> Configure Tomact -> Start)! Run the program and viola, you just indexed all of your files! (In a real world scenario, you'd obviously batch this operation, getting only x amount from the database, possibly event multithreading it to maximize performance, but again this is just a demo :) ). Now let's see if in fact our indexing worked. Open your browser to http://localhost:8983/solr (or whatever the Solr Url is) and click on Solr Admin. In the Search box enter "*:*" (the Lucene equivalent of SELECT *) and click the Search button. You SHOULD see this:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/1143355_search-xml.jpg"><br /><br />(depending on how many files you decided to download using the Harvester application you'll see different totals). Congrats! You've successfully indexed the files!<br /><br /><span style="font-weight:bold;">Part 4.2: Searching the Files</span><br /><br />Now we want to search using C#. That too is VERY easy using SolrNet. The only thing to remember here, is like I mentioned earlier, we didn't STORE the fields in Solr. All we stored was the FileID. Therefore, we need to first retrieve those file id's, and then hit the database to get the rest of the information. It may seem like double work, but TRUST me!!! when dealing with larger data sets, it's MUCH faster. So, first let's create a class to hold the FileID's:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">internal</span> <span class="kwrd">class</span> FileIDResult<br /> {<br /> [SolrField(<span class="str">"fileid"</span>)]<br /> <span class="kwrd">public</span> <span class="kwrd">int</span> FileID { get; set; }<br /> }<br /></pre><br /><br />Same concept like Indexing. We use the SolrField attributes for the properties that will map to the Index fields. <br /><br />Now, we can write some code to execute the Search. There are a few parameters I'd like to discuss first. Aside from the search query itself, you need to specify the amount per page, and which number to start from. Solr has paging built right into it, so the way it works is, you specify how many items you want per page, and then how many items to skip over. So for example, if you have 100 results, and you have 10 items per page, and you want Page 3, you'd start at item 30 (it's zero based). With that in mind, here's the searching code:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">internal</span> <span class="kwrd">static</span> <span class="kwrd">class</span> SolrOperationsCache<T><br /> <span class="kwrd">where</span> T: <span class="kwrd">new</span>()<br /> {<br /> <span class="kwrd">private</span> <span class="kwrd">static</span> ISolrOperations<T> solrOperations;<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> ISolrOperations<T> GetSolrOperations(<span class="kwrd">string</span> solrUrl)<br /> {<br /> <span class="kwrd">if</span> (solrOperations == <span class="kwrd">null</span>)<br /> {<br /> Startup.Init<T>(solrUrl);<br /> solrOperations = ServiceLocator.Current.GetInstance<ISolrOperations<T>>();<br /> }<br /><br /> <span class="kwrd">return</span> solrOperations;<br /> }<br /><br /> }</pre><br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> BasicSearcher<br /> {<br /> <span class="kwrd">private</span> <span class="kwrd">string</span> connectionString;<br /> <span class="kwrd">private</span> <span class="kwrd">string</span> solrUrl;<br /><br /> <span class="kwrd">public</span> BasicSearcher(<span class="kwrd">string</span> connectionString, <span class="kwrd">string</span> solrUrl)<br /> {<br /> <span class="kwrd">this</span>.connectionString = connectionString;<br /> <span class="kwrd">this</span>.solrUrl = solrUrl;<br /> }<br /><br /> <span class="kwrd">public</span> SearchResults Search(<span class="kwrd">string</span> query, <span class="kwrd">int</span> resultsPerPage, <span class="kwrd">int</span> pageNumber)<br /> {<br /> var solrWorker = SolrOperationsCache<FileIDResult>.GetSolrOperations(<span class="kwrd">this</span>.solrUrl);<br /><br /> QueryOptions options = <span class="kwrd">new</span> QueryOptions<br /> {<br /> Rows = resultsPerPage,<br /> Start = (pageNumber - 1) * resultsPerPage,<br /> };<br /><br /> ISolrQueryResults<FileIDResult> results = solrWorker.Query(query, options);<br /> var textFiles = <span class="kwrd">new</span> TextFileRepository(<span class="kwrd">this</span>.connectionString)<br /> .GetTextFiles(results.Select(r => r.FileID));<br /><br /><br /> var searchResults = <span class="kwrd">new</span> SearchResults<br /> {<br /> Results = textFiles,<br /> QueryTime = results.Header.QTime,<br /> TotalResults = results.NumFound<br /> };<br /><br /> <span class="kwrd">return</span> searchResults;<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> SearchResults<br /> {<br /> <span class="kwrd">public</span> IEnumerable<TextFile> Results { get; set; }<br /> <span class="kwrd">public</span> <span class="kwrd">int</span> QueryTime { get; set; }<br /> <span class="kwrd">public</span> <span class="kwrd">int</span> TotalResults { get; set; }<br /> }</pre><br /><br />Same idea as before. Get an instance to the ISolrOperations, and call the Query method. I used the overload that takes a QueryOptions object so that I can specify the page number and items per page. The result that comes back from that method call is an ISolrQueryResults which in addition to the search results itself, has some metrics. I wrapped all that up in the SearchResults class. Once we have the file id's we can hit the database, and get the rest of the data.<br /><br />Let's give it a whirl:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Program<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)<br /> {<br /> <span class="kwrd">string</span> connectionString = <span class="str">""</span>;<br /> <span class="kwrd">string</span> solrUrl = <span class="str">""</span>;<br /><br /> BasicSearcher searcher = <span class="kwrd">new</span> BasicSearcher(connectionString, solrUrl);<br /> var results = searcher.Search(<span class="str">"*:*"</span>, 10, 1);<br /> <span class="kwrd">foreach</span> (TextFile file <span class="kwrd">in</span> results.Results)<br /> {<br /> Console.WriteLine(<span class="str">"FileID: {0}, Title: {1}"</span>,file.FileID,file.Title);<br /> }<br /> }<br /> }</pre><br /><br />If you run this, you should see the file id's and titles for the first 10 documents! Congratulations, you've just executed a search!!<br /><br />OK, this has gotten WAAAAAY longer than I ever imagined. There's ALOT going on here, I won't deny that. There's a few closing random points I'd like to make:<br /><br /><ul><br /><li>There are many various Tokenizers and Analyzers for various data. If you need to tweak one and create your own, you're SOL to do it in C#, you'll have to blow the dust off that old Java book and do it there.</li><br /><li>The actual index is stored under $\solr\data\index. Sometimes it's useful to actually look into the index files and read them. For that you can use <a href="http://www.getopt.org/luke/">Luke (a standalone Java application.)</a></li><br /><li>In the real world, you'd possibly have your Indexing Server somewhere other than where the data is. Keep that in mind, as the XML sent across can get quite big, so see if you can optimize that.</li><br /></ul><br /><br />There's so much more to Lucene and Solr than what I covered here. Here are some links for more reading:<br /><br /><a href="http://lucene.apache.org/java/docs/index.html">Lucene Home Page</a><br /><a href="http://www.darksleep.com/lucene/">Lucene tutorial.</a> (While this is an actual Lucene tutorial of how to use the Lucene Java libraries, it has some great insight in to what's happening behind the scenes.)<br /><a href="http://lucene.apache.org/solr/">Solr Home Page</a><br /><a href="http://wiki.apache.org/solr/">Solr Wiki</a><br /><a href="http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters">The various Tokenizers an Analyzers available from Solr</a><br /><br />That's all I can think of for now. If there's anything else, I'll add it in the future. <br /><br />Lastly,<a href="http://www.box.net/shared/efcss6fnjp"> here's a zip file containing everything I covered in this post</a>. You'll find the TextFileHarvester app. You'll find the solr configuration files I've used for this demo. You'll also find a simple library I created to wrap the indexing and searching functionality of these text files, as well as a basic windows application to test both. Good luck, and Happy Coding!<br /><br />P.S. This tutorial took a lot of time and effort. If you find it useful, just drop me a a line in the comments.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com36tag:blogger.com,1999:blog-5611706923356552090.post-76508517117209441892010-01-07T22:49:00.005-05:002010-01-13T09:53:58.010-05:00Comparing C# structs to null. Can you or not?A while back I <a href="http://crazorsharp.blogspot.com/2009/06/creating-splash-screen-in-net-with.html">posted a blog</a> about creating a Splash Screen in WinForms. While writing that blog, I was running into problems when calling BeginInvoke on the form, and I was getting this error:<br /><blockquote><br />Invoke or BeginInvoke cannot be called on a control until the window handle has been created.</blockquote><br /><br />Every Form has a Handle that gets assigned to it by Windows. Therefore, I figured I'd just check to see if the handle is null:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">if</span>(<span class="kwrd">this</span>.Handle == <span class="kwrd">null</span>)<br />{<br /> <span class="kwrd">return</span>; <span class="rem">//don't do anything</span><br />}</pre><br /><br />When that didn't work, I started digging in a little deeper, and found out that the Form.Handle is of type <a href="http://msdn.microsoft.com/en-us/library/system.intptr%28VS.71%29.aspx">IntPtr</a> which is actually a struct. Structs as everyone knows are value types which can't be null so therefore, the null check would always fail and therefore the return statement never got hit.(The fix for that isn't related to this post, so I won't go into detail.)<br /><br />The question that came to mind though right away was, why did that compile? If you try to compare a struct to null, the compiler complains right? So just to make sure I wasn't going nuts, I quickly whipped up this code sample:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">class</span> Program<br /> {<br /> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)<br /> {<br /> MyStruct ms = <span class="kwrd">new</span> MyStruct();<br /> <span class="kwrd">if</span> (ms == <span class="kwrd">null</span>)<br /> {<br /> Console.WriteLine(<span class="str">"Can't get here."</span>);<br /> }<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">struct</span> MyStruct { }<br /></pre><br /><br />And sure enough, as soon as I tried compiling this, I got this error:<br /><blockquote><br />Operator '==' cannot be applied to operands of type 'StructDemo.MyStruct' and '<null>'</blockquote><br /><br />OK, so then how the heck can IntPtr be compared to null, but my struct can't? What's Microsoft know that I don't? So then I decided to look at the metadata for IntPtr:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> [Serializable]<br /> [ComVisible(<span class="kwrd">true</span>)]<br /> <span class="kwrd">public</span> <span class="kwrd">struct</span> IntPtr : ISerializable<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">readonly</span> IntPtr Zero;<br /><br /> [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]<br /> <span class="kwrd">public</span> IntPtr(<span class="kwrd">int</span> <span class="kwrd">value</span>);<br /> <br /> [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]<br /> <span class="kwrd">public</span> IntPtr(<span class="kwrd">long</span> <span class="kwrd">value</span>);<br /><br /> [CLSCompliant(<span class="kwrd">false</span>)]<br /> [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]<br /> <span class="kwrd">public</span> IntPtr(<span class="kwrd">void</span>* <span class="kwrd">value</span>);<br /><br /> [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> <span class="kwrd">operator</span> !=(IntPtr value1, IntPtr value2);<br /> <br /> [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> <span class="kwrd">operator</span> ==(IntPtr value1, IntPtr value2);<br /> <br /> [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">explicit</span> <span class="kwrd">operator</span> IntPtr(<span class="kwrd">int</span> <span class="kwrd">value</span>);<br /> <br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">explicit</span> <span class="kwrd">operator</span> <span class="kwrd">int</span>(IntPtr <span class="kwrd">value</span>);<br /> <br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">explicit</span> <span class="kwrd">operator</span> <span class="kwrd">long</span>(IntPtr <span class="kwrd">value</span>);<br /> <br /> [CLSCompliant(<span class="kwrd">false</span>)]<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">explicit</span> <span class="kwrd">operator</span> <span class="kwrd">void</span>*(IntPtr <span class="kwrd">value</span>);<br /> <br /> [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">explicit</span> <span class="kwrd">operator</span> IntPtr(<span class="kwrd">long</span> <span class="kwrd">value</span>);<br /> <br /> [CLSCompliant(<span class="kwrd">false</span>)]<br /> [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">explicit</span> <span class="kwrd">operator</span> IntPtr(<span class="kwrd">void</span>* <span class="kwrd">value</span>);<br /> <br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">int</span> Size { get; }<br /> <br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">bool</span> Equals(<span class="kwrd">object</span> obj);<br /> <br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">int</span> GetHashCode();<br /> <br /> [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]<br /> <span class="kwrd">public</span> <span class="kwrd">int</span> ToInt32();<br /> <br /> [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]<br /> <span class="kwrd">public</span> <span class="kwrd">long</span> ToInt64();<br /> <br /> [CLSCompliant(<span class="kwrd">false</span>)]<br /> [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]<br /> <span class="kwrd">public</span> <span class="kwrd">void</span>* ToPointer();<br /> <br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> ToString();<br /> <br /> <span class="kwrd">public</span> <span class="kwrd">string</span> ToString(<span class="kwrd">string</span> format);<br /> }</pre><br /><br />OK, so I decided to try and copy bit by bit to see if I can make the error go away. First I tried making it Serializable:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">struct</span> MyStruct : ISerializable<br /> {<br /> <span class="preproc">#region</span> ISerializable Members<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> GetObjectData(SerializationInfo info, StreamingContext context)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /><br /> <span class="preproc">#endregion</span><br /> }</pre><br /><br />No luck. Still won't compile. Next, I decided to add the Equals and GetHashCode overloads:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">struct</span> MyStruct : ISerializable<br /> {<br /> <span class="preproc">#region</span> ISerializable Members<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> GetObjectData(SerializationInfo info, StreamingContext context)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /><br /> <span class="preproc">#endregion</span><br /><br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">int</span> GetHashCode()<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">base</span>.GetHashCode();<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">bool</span> Equals(<span class="kwrd">object</span> obj)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">base</span>.Equals(obj);<br /> }<br /> }<br /></pre><br /><br />Still no luck. Finally, this is what made the error go away:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">struct</span> MyStruct : ISerializable<br /> {<br /> <span class="preproc">#region</span> ISerializable Members<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> GetObjectData(SerializationInfo info, StreamingContext context)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> NotImplementedException();<br /> }<br /><br /> <span class="preproc">#endregion</span><br /><br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">int</span> GetHashCode()<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">base</span>.GetHashCode();<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">bool</span> Equals(<span class="kwrd">object</span> obj)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">base</span>.Equals(obj);<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> <span class="kwrd">operator</span> ==(MyStruct m1, MyStruct m2)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">true</span>;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> <span class="kwrd">operator</span> !=(MyStruct m1, MyStruct m2)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">false</span>;<br /> }<br /> }<br /></pre><br /><br /><br />Huh? Overriding the equals and not equals operator? Why? Both of those methods still only take MyStruct as arguments which can't be null?! I still can't pass null to either one of those methods, so why does the compiler allow it all of a sudden?<br /><br />After much digging, I finally found my answer and I'll try to do my best to explain. Since .Net 2.0 with the introduction of Nullable Types, there's now an implicit conversion between any value type and it's nullable type. Meaning, I can always do this safely:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">int</span> x = 10;<br /> Nullable<<span class="kwrd">int</span>> y = x;</pre><br /><br />Therefore, whenever we override the == operator, the C# compiler gives us another one for free. It also allows us to compare Nullable versions of that type. Meaning, when you do this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> <span class="kwrd">operator</span> ==(MyStruct m1, MyStruct m2)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">true</span>;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> <span class="kwrd">operator</span> !=(MyStruct m1, MyStruct m2)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">false</span>;<br /> }<br /></pre><br /><br />You're also getting this for free:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> <span class="kwrd">operator</span> ==(Nullable<MyStruct> m1, Nullable<MyStruct> m2)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">true</span>;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> <span class="kwrd">operator</span> !=(Nullable<MyStruct> m1, Nullable<MyStruct> m2)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">false</span>;<br /> }</pre><br /><br />So that's why, when you compare your struct instance to null, it casts your struct instance to a nullable type (implicitly), and calls the overload which takes two nullables. Therefore, your code compiles. Of course it can never be null and the if check will always fail, but the compiler now thinks it's OK. Heh, you learn something new every day I guess...A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com1tag:blogger.com,1999:blog-5611706923356552090.post-74424765686954863892009-12-24T12:38:00.003-05:002009-12-24T14:41:59.059-05:00Powershell like command line arguments in a C# Console Application<span style="font-weight:bold;">Source Code:</span> <a href="http://www.box.net/shared/5l587aig4k">http://www.box.net/shared/5l587aig4k</a><br /><br />Here at work, we use Powershell to script some automated integration tests. Sometimes, simple scripts aren't enough, and we need to resort to writing <a href = "http://technet.microsoft.com/en-us/scriptcenter/dd772285.aspx">Cmdlets.</a> For the purpose of this blog post, all you really need to know about Cmdlets is that they're basically a C# class that's invoked from the Powershell command line. What I thought was really cool with Cmdlets, is the way it deals with command-line arguments. <br /><br />Basically, there's a <a href="http://msdn.microsoft.com/en-us/library/system.management.automation.parameterattribute%28VS.85%29.aspx">ParameterAttribute</a> that you put on your properties, and those properties then get set from the command line. Here's a simple example:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> MyCmdlet : Cmdlet<br /> {<br /> [Parameter]<br /> <span class="kwrd">public</span> <span class="kwrd">int</span> IntArg { get; set; }<br /> }</pre><br /><br /><br />Then from the Powershell command line you would do something like this:<br /><br /><span style="font-weight:bold;">PS>MyCmdlet -IntArg 100</span><br /><br />And then within your Cmdlet class, your IntArg property will automatically be set to 100. <br /><br />It then dawned on me, we have many Console apps at work that each have their own way of parsing the arguments. Now I know there are many command line parsers out there, but I thought, wouldn't be be cool if we can have the kind of syntax for invoking Console applications just like Powershell does.<br /><br />I won't explain all of the code, you can download it at the bottom of this post, and dig in yourself, but I'll just highlight a few points. Firstly, this is how you can use this library:<br /><br />Say you have an application, that you need to pass in different characteristics of a person. Things like, Name, Age, Height and Email Address, you'd want to be able to invoke the application like this:<br /><br />MyConsoleApp.exe -Name "Alex Friedman" -Age 27 -Height 69.5 -EmailAddress "a.friedman07@gmail.com"<br /><br />First you'd need to create a Person class to represent all the command line arguments:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">internal</span> <span class="kwrd">class</span> Person<br /> {<br /> [Parameter]<br /> <span class="kwrd">public</span> <span class="kwrd">string</span> Name { get; set; }<br /><br /> [Parameter]<br /> <span class="kwrd">public</span> <span class="kwrd">int</span> Age { get; set; }<br /><br /> [Parameter]<br /> <span class="kwrd">public</span> <span class="kwrd">double</span> Height { get; set; }<br /><br /> [Parameter(Mandatory=<span class="kwrd">true</span>)]<br /> <span class="kwrd">public</span> <span class="kwrd">string</span> EmailAddress { get; set; }<br /> }</pre><br /><br />Then, in your main method, you'd do this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> ArgsSetter<Person> argsSetter = <span class="kwrd">new</span> ArgsSetter<Person>(args);<br /> Person person = argsSetter.BuildParameterObject();<br /></pre><br /><br />And that's it. Your person object will have all the properties set. The thing to note here is that this library can deal with all primitive types including strings. Remember, all arguments come in as a string, even the number 27 for example gets passed in as the string representation of "27", yet it gets converted for you automatically to an int.<br /><br />A few other things to note, is the error handling. <strong>I didn't implement extensive validation in this library.</strong> What I did implement was two things. First, there's an IValidator interface that does some error checking for fatal errors; errors that would prevent from even attempting to parse. I provide a DefaultValidator that checks that there are an even number of elements in the args array. You can think of the command line arguments as a Key-Value pair; the key being the argument name, and the value being the argument value. Therefore, if there's an odd number of args, something isn't right. Also, it makes sure to check that arguments begin with a "-". If that's not enough, you can implement your own IValidator.<br /><br />The second part of error handling, is to make sure that the values are correct, and that the Mandatory arguments have been provided. To get that information you do something like this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">foreach</span> (var error <span class="kwrd">in</span> setter.Errors)<br /> {<br /> Console.WriteLine(<span class="str">"Paramname: {0}, Error: {1}"</span>, error.ArgumentName, error.ErrorType);<br /> }<br /></pre><br /><br />The ArgsSetter class has an Errors collection that gives you all the errors that occurred. <br /><span style="font-weight:bold;"><br />Here's a link to the source code. It contains the actual library, as well as some unit tests: </span> <a href="http://www.box.net/shared/5l587aig4k">http://www.box.net/shared/5l587aig4k</a><br /><br />That's pretty much all there is to it. Feel free to download the source code and mess with it. I'd like to stress the point that there's alot more that can be done with this, and if you do use this and add something, feel free to drop me an email. Also, any constructive criticism is always welcome. Enjoy!A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com1tag:blogger.com,1999:blog-5611706923356552090.post-27929727344474303372009-08-19T20:37:00.004-04:002009-08-19T21:45:49.318-04:00Rethrowing an Exception without resetting the Stack Trace.<b>Source code: <a href ="http://www.box.net/shared/kjkgq36itq">http://www.box.net/shared/kjkgq36itq</a></b><br><br />Exception handling in .NET is a complicated subject. It's complicated and always spawns all kinds of debates. I won't post my opinion or anything like that, but I want to point out a subtle yet important difference when re-throwing an exception. The two ways you can re-throw an exception are:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">try</span><br /> {<br /> DoSomeExceptionThrowingMethod();<br /> }<br /> <span class="kwrd">catch</span> (Exception ex)<br /> {<br /><br /> <span class="kwrd">throw</span> ex;<br /> }<br /><br /><br /> <span class="kwrd">try</span><br /> {<br /> DoSomeExceptionThrowingMethod();<br /> }<br /> <span class="kwrd">catch</span> (Exception ex)<br /> {<br /><br /> <span class="kwrd">throw</span>;<br /> }<br /></pre><br /><br />As you can see, the only difference is in the catch block where I'm calling throw. In the first case I'm calling throw ex, while in the second case I'm simply calling throw. What's the difference?<br /><br />Well when you're simply calling throw, you're effectivley calling "rethrow" meaning "re throw the exception you just caught". When you're calling "throw ex" you're basically just saying "throw" and you're not rethrowing the exception you just caught. That doesn't make much sense, so let's whip up a code sample:<br /><br />First, we'll have a class that has one method which throws an exception:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> ExceptionThrower<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">void</span> InvalidMethod()<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> InvalidOperationException(<span class="str">"This method is invalid."</span>);<br /> }<br /> }<br /></pre><br /><br />Now, we'll add a few layers of method calling to this demo so we can make the actual stack trace a little bigger (I'll explain more soon):<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Layer1<br /> {<br /> <span class="kwrd">private</span> ExceptionThrower thrower;<br /><br /> <span class="kwrd">public</span> Layer1()<br /> {<br /> <span class="kwrd">this</span>.thrower = <span class="kwrd">new</span> ExceptionThrower();<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> Layer1Method()<br /> {<br /> <span class="kwrd">this</span>.thrower.InvalidMethod();<br /> }<br /> }<br /></pre><br /><br />Here's one layer of method calling, now we'll add one more:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Layer2<br /> {<br /> <span class="kwrd">private</span> Layer1 layer1;<br /><br /> <span class="kwrd">public</span> Layer2()<br /> {<br /> <span class="kwrd">this</span>.layer1 = <span class="kwrd">new</span> Layer1();<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> Layer2Method()<br /> {<br /> <span class="kwrd">this</span>.layer1.Layer1Method();<br /> }<br /> }</pre><br /><br />These classes aren't doing much more than just wrapping the method calls from the object they have internally.<br /><br />Now, let's code up our main method:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">class</span> Program<br /> {<br /> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)<br /> {<br /> <span class="kwrd">try</span><br /> {<br /> Console.WriteLine(<span class="str">"Calling KeepStackTrace"</span>);<br /> KeepStackTrace();<br /> }<br /> <span class="kwrd">catch</span> (InvalidOperationException ex)<br /> {<br /> Console.WriteLine(ex.StackTrace);<br /> }<br /><br /> <span class="kwrd">try</span><br /> {<br /> Console.WriteLine(<span class="str">"Calling ResetStackTrace"</span>);<br /> ResetStackTrace();<br /> }<br /> <span class="kwrd">catch</span> (InvalidOperationException ex)<br /> {<br /> Console.WriteLine(ex.StackTrace);<br /> }<br /><br /> Console.ReadKey(<span class="kwrd">true</span>);<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> KeepStackTrace()<br /> {<br /> Layer2 l2 = <span class="kwrd">new</span> Layer2();<br /> <span class="kwrd">try</span><br /> {<br /> l2.Layer2Method();<br /> }<br /> <span class="kwrd">catch</span> (InvalidOperationException ex)<br /> {<br /> <span class="kwrd">throw</span>;<br /> }<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> ResetStackTrace()<br /> {<br /> Layer2 l2 = <span class="kwrd">new</span> Layer2();<br /> <span class="kwrd">try</span><br /> {<br /> l2.Layer2Method();<br /> }<br /> <span class="kwrd">catch</span> (InvalidOperationException ex)<br /> {<br /> <span class="kwrd">throw</span> ex;<br /> }<br /> }<br /> }<br /></pre><br /><br />So basically we have two methods that call into our Layer2 class. One wraps the method in a try / catch but just calls throw, while the other calls throw ex. In the main method, we output the Stack Trace of the exception. Let's examine the output:<br /><br /><b>Calling KeepStackTrace<br /><br /> at ExceptionReThrow.ExceptionThrower.InvalidMethod() in C:\Users\Alex\Documents\Visual Studio 2008\Projects\ExceptionReThrow\ExceptionReThrow\ExceptionThrower.cs:line 12<br /> at ExceptionReThrow.Layer1.Layer1Method() in C:\Users\Alex\Documents\Visual Studio 2008\Projects\ExceptionReThrow\ExceptionReThrow\Layer1.cs:line 19<br /> at ExceptionReThrow.Layer2.Layer2Method() in C:\Users\Alex\Documents\Visual Studio 2008\Projects\ExceptionReThrow\ExceptionReThrow\Layer2.cs:line 19<br /> at ExceptionReThrow.Program.KeepStackTrace() in C:\Users\Alex\Documents\Visual Studio 2008\Projects\ExceptionReThrow\ExceptionReThrow\Program.cs:line 48<br /> at ExceptionReThrow.Program.Main(String[] args) in C:\Users\Alex\Documents\Visual Studio 2008\Projects\ExceptionReThrow\ExceptionReThrow\Program.cs:line 19<br /><br />Calling ResetStackTrace<br /><br /> at ExceptionReThrow.Program.ResetStackTrace() in C:\Users\Alex\Documents\Visual Studio 2008\Projects\ExceptionReThrow\ExceptionReThrow\Program.cs:line 61<br /> at ExceptionReThrow.Program.Main(String[] args) in C:\Users\Alex\Documents\Visual Studio 2008\Projects\ExceptionReThrow\ExceptionReThrow\Program.cs:line 29</b><br /><br />As you can tell, when calling the KeepStackTrace which simply did "throw" the entire stack trace with all the layers are kept and we can see it all the way down to where the exception originated. <br /><br />When calling ResetStrackTrace though, the method where we do "throw ex", you'll notice that all we see is down till our ResetStackTrace method. We don't see anything past that, even though that's not really where the exception originated.<br /><br />Bottom line, for the most part, this isn't all that relevant because you really shouldn't be catching exceptions if you don't plan on doing anything with it. However, if you do want to at least log it, but let it bubble up, be sure to do "throw" so that when the Exception does finally bubble to the top, you have the entire stack trace.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com0tag:blogger.com,1999:blog-5611706923356552090.post-47883551773506703562009-07-30T18:27:00.003-04:002009-07-30T19:09:52.827-04:00Passing objects using the ref keyword...Wait, aren't objects *always* passed by reference???For the past month I've been on the job market and have been exposed to all kinds of technical questions. Most of them were run of the mill, but every once and a while I'd get asked a question that made me stop and think. Perfect for a guy with a blog, because now you have tons more stuff to blog about right?<br /><br />P.S. For those interested, I accepted an offer earlier this week at a company called <a href="http://www.biaprotect.com">BIA</a>. They are a computer forensics firm and I'm real excited to start!<br /><br />So one question that I really liked, was the point of this blog post. The interviewer actually informed me that I was only one out of one hundred that got this question right. Not believing that these numbers were true, I asked everyone on my team at my old job, and only one of them sort of half knew. The others were completely stumped. I guess it is something that many developers just glance over. <br /><br />OK, so what is this question already?? Well it goes something like this: <span style="font-weight:bold;">"What's the difference between passing an object to a method the standard way, and passing an object to a method using the <a href="http://msdn.microsoft.com/en-us/library/14akc2c7%28VS.71%29.aspx">ref</a> keyword?"</span><br /><br />Let's break it down. Let's first talk about what the ref keyword does when it comes to value types. Simple example:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)<br /> {<br /> <span class="kwrd">int</span> number = 10;<br /> <br /> Add5(number);<br /> Console.WriteLine(number);<br /><br /> Add5(<span class="kwrd">ref</span> number);<br /> Console.WriteLine(number);<br /><br /> Console.ReadKey(<span class="kwrd">true</span>);<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Add5(<span class="kwrd">int</span> x)<br /> {<br /> x += 5;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Add5(<span class="kwrd">ref</span> <span class="kwrd">int</span> x)<br /> {<br /> x += 5;<br /> }<br /></pre><br /><br />Before trying to run this, see if you can guess what the output would be.....<br /><br /><br />Answer: The first Console.Writline outputs 10 and the second one outputs 15. Why? Well, the definition of a "value type" is that when passing it to a method, it's passed by value. Meaning, not the actual variable itself is passed to the method, rather a <span style="font-weight:bold;"><span style="font-style:italic;">copy</span></span> of the value is passed to the method. Therefore, when calling the first method, just adding 5 to the variable that was passed in, does NOT affect the variable in the main method, because we only added 5 to the COPY of the x variable not the actual one.<br /><br />In the second method call though, we're passing the variable using the ref keyword. This changes the behavior and actually DOES pass the actual variable itself to the method. Therefore, in the second method, when adding 5 to the value being passed in, you're actually messing with the same exact variable that's in the main method. Therefore, it outputs 15 showing the changes DID take effect. <br /><br />So now we have an understanding of how value types work, and how ref changes the behavior. Let's talk about objects now, which are passed by reference. I'll start with another example:<br /><br />First a simple Person class:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Person<br /> {<br /> <span class="kwrd">public</span> Person(<span class="kwrd">string</span> name, <span class="kwrd">int</span> age)<br /> {<br /> <span class="kwrd">this</span>.Name = name;<br /> <span class="kwrd">this</span>.Age = age;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> ToString()<br /> {<br /> <span class="kwrd">return</span> String.Format(<span class="str">"{0} is {1} years old."</span>, <span class="kwrd">this</span>.Name, <span class="kwrd">this</span>.Age);<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">string</span> Name { get; set; }<br /> <span class="kwrd">public</span> <span class="kwrd">int</span> Age { get; set; }<br /><br /> }<br /></pre><br /><br />Simple class with two properties. Name and Age. Also, the ToString is overridden to make it easier to demonstrate.<br /><br />Now, let's say we had something like this in our Program.cs:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)<br /> {<br /> var alex = <span class="kwrd">new</span> Person(<span class="str">"Alex"</span>, 27);<br /> <br /> ChangePerson(alex);<br /> Console.WriteLine(alex);<br /> <br /> Console.ReadKey(<span class="kwrd">true</span>);<br /> }<br /><br /> <br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> ChangePerson(Person p)<br /> {<br /> p.Age += 5;<br /> }<br /></pre><br /><br />Try guessing what the output would be for this program.<br /><br />Answer: Alex is 32 years old.<br /><br />If you're paying attention you'll notice that this is different than how it was with value types. The change in the method DID affect the one in the main method! That's because objects are passed by reference, meaning that a reference (pointer) to the SAME object is being passed to the method. So in the method itself, you still have a reference to the same object that exists in the main method. Therefore, when you make changes, it does show up back in the main.<br /><br />So back to the original question: If all objects are passed by reference, what's the point of the ref keyword when passing an object to a method??<br /><br />So here's the deal. Let's talk in terms of the stack and the heap. In the current version of the CLR value types are stored on the stack, and reference types are stored on the heap. However, and this is key, for reference types, a *pointer* to that object is ALSO stored on the stack! Ok, so why is this so important? Well, I sort of mispoke earlier when I said objects are passed by refernece. I didn't give you the whole picture. What's actually happening is that a <span style="font-weight:bold;"><span style="font-style:italic;">copy</span> of the pointer is being passed to the the method.</span> So while you are referencing the same object in memory in the method and the one in the main, the POINTER variable on the stack, is NOT the same. HOWEVER, when using the ref keyword, the pointer <span style="font-style:italic;">itself </span> is passed to the method, not a copy of it! So when you're inside the method itself, you're dealing with the exact same pointer variable that's in the main.<br /><br />The only way to explain is with an example:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)<br /> {<br /> var alex = <span class="kwrd">new</span> Person(<span class="str">"Alex"</span>, 27);<br /> <br /> ChangePerson(alex);<br /> Console.WriteLine(alex);<br /><br /> ChangePerson(<span class="kwrd">ref</span> alex);<br /> Console.WriteLine(alex);<br /> <br /> Console.ReadKey(<span class="kwrd">true</span>);<br /> }<br /><br /> <br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> ChangePerson(Person p)<br /> {<br /> p = <span class="kwrd">new</span> Person(<span class="str">"Alex"</span>, 35);<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> ChangePerson(<span class="kwrd">ref</span> Person p)<br /> {<br /> p = <span class="kwrd">new</span> Person(<span class="str">"Alex"</span>, 45);<br /> }<br /></pre><br /><br />Here we have two methods that look the same. The only difference is the ref keyword. What the method is doing, is it's assigning a NEW person object to the Person p (the pointer) that was passed in to the method. However, if you run this program you'll see that the first Console.Writeline still outputs 27 years old, even though we assigned it to a person object that's 35 years old! The reason for this is because the pointer itself was passed by VALUE so when you're assigning a new person object, you're not assigning it to the same pointer referenced in the main.<br /><br />In the second case however, since we're using the ref keyword, the pointer in the method is the SAME one that's in the main method. Therefore, the second Console.Writeline outputs 45 years old, because the pointer in the main, is now pointing to the object that was assigned to it in the method.<br /><br />Personally I've never used this yet in production code, but if you understand this, then that means you understand the nitty gritty details of how parameters are passed around. Very impressive on interviews :-)A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com4tag:blogger.com,1999:blog-5611706923356552090.post-83424220340115414062009-07-14T11:06:00.009-04:002009-07-14T21:36:57.949-04:00Using JQuery to post a Form with ASP.NET MVC with AJAX<b>Source code:</b><span style="font-weight:bold;"><a href="http://www.box.net/shared/2to3vfajqp">http://www.box.net/shared/2to3vfajqp</a></span><span style="font-weight:bold;color:red"> In order for this sample to work on your machine, you need to have the Northwind database, and you need to configure the connection string in the HomeController.</span><br /><br />When you install ASP.NET MVC, you'll notice that when you create a new project, the latest jQuery libraries get added for you as well. For those of you who don't know what jQuery is, think of it as a layer of abstraction for common tasks you would do with javascript. Instead of having to rewrite tons of javascript to let's say, do some animation, or post to a server with AJAX, jQuery makes it all extremely simple. I've found that there aren't that many tutorials online for getting started with jQuery and AJAX when using ASP.NET MVC, so I figured I'll share what I've learned so far in the hopes that maybe others can get some insight.<br /><br />The premise here will be simple. We'll be using the Northwind database (specifically the Products table) to display a list of Products and some of their attributes. Then, there will be a textbox on top of the list. When the user enters some text into the textbox, it will post back to the server via AJAX and find any products that match what the user entered. Here's what it will look like:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/868205_mvc-products.jpg"><br><br /><br />So first I started with a simple ASP.NET MVC application. I'll be using the standard project for this tutorial. I then added a NorthwindDataContext to the Models folder with only the Products table from the Northwind database. Then, I added a repository that will help us retrieve the items from the database. Here's the code for the repository:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Collections.Generic;<br /><span class="kwrd">using</span> System.Linq;<br /><span class="kwrd">using</span> System.Web;<br /><br /><span class="kwrd">namespace</span> MVCJqueryDemo.Models<br />{<br /> <span class="kwrd">public</span> <span class="kwrd">class</span> NorthwindRepository : IDisposable<br /> {<br /> <span class="preproc">#region</span> Members<br /><br /> <span class="kwrd">private</span> NorthwindDataContext dataContext;<br /><br /> <span class="preproc">#endregion</span><br /><br /> <span class="preproc">#region</span> Constructors<br /><br /> <span class="kwrd">public</span> NorthwindRepository()<br /> : <span class="kwrd">this</span>(<span class="kwrd">null</span>)<br /> {<br /> }<br /><br /> <span class="kwrd">public</span> NorthwindRepository(<span class="kwrd">string</span> connectionString)<br /> {<br /> dataContext = String.IsNullOrEmpty(connectionString) ? <span class="kwrd">new</span> NorthwindDataContext()<br /> : <span class="kwrd">new</span> NorthwindDataContext(connectionString);<br /> }<br /><br /> <span class="preproc">#endregion</span><br /><br /> <span class="preproc">#region</span> Methods<br /><br /> <span class="kwrd">public</span> IEnumerable<Product> GetAllProducts()<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.dataContext.Products.ToList();<br /> }<br /><br /> <span class="kwrd">public</span> IEnumerable<Product> GetProductsByName(<span class="kwrd">string</span> name)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.dataContext.Products.Where(p => p.ProductName.Contains(name)).ToList();<br /> }<br /><br /> <span class="preproc">#endregion</span><br /><br /> <span class="preproc">#region</span> IDisposable<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> Dispose()<br /> {<br /> <span class="kwrd">this</span>.dataContext.Dispose();<br /> }<br /><br /> <span class="preproc">#endregion</span><br /> }<br />}<br /></pre><br /><br />So this class will help us retrieve what we need from the db. Now, over in the Home controller, I've added two actions:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> HomeController : Controller<br /> {<br /> <span class="preproc">#region</span> Members<br /><br /> <span class="rem">//CHANGE THIS CONNECTION STRING IF YOUR NORTHWIND IS IN A DIFFERENT LOCATION!!!!</span><br /> <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">string</span> CONNECTIONSTRING = <span class="str">"Data Source=.;Initial Catalog=Northwind;Integrated Security=True"</span>;<br /><br /> <span class="preproc">#endregion</span><br /><br /> <span class="kwrd">public</span> ActionResult Products()<br /> {<br /> <span class="kwrd">using</span> (var repository = <span class="kwrd">new</span> NorthwindRepository(CONNECTIONSTRING))<br /> {<br /> var allProducts = repository.GetAllProducts();<br /> <span class="kwrd">return</span> View(allProducts);<br /> }<br /> }<br /><br /> [AcceptVerbs(HttpVerbs.Post)]<br /> <span class="kwrd">public</span> ActionResult Search(<span class="kwrd">string</span> name)<br /> {<br /> <span class="kwrd">using</span> (var repository = <span class="kwrd">new</span> NorthwindRepository(CONNECTIONSTRING))<br /> {<br /> var result = repository.GetProductsByName(name);<br /> <span class="kwrd">return</span> View(<span class="str">"ProductsPartial"</span>, result);<br /> }<br /> }<br /> }<br /></pre><br /><br />So there are two methods here. Once will be ../Home/Products and the other will be a url where we'll post to ../Home/Search. <br /><br />The first one is straight forward. It just hits the repository for all the products, and passes it on to the View. We can see from this, that there's a Products View. Here's the code for the Products View:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><%@ Page Title=<span class="str">""</span> Language=<span class="str">"C#"</span> MasterPageFile=<span class="str">"~/Views/Shared/Site.Master"</span> Inherits=<span class="str">"System.Web.Mvc.ViewPage<IEnumerable<Product>>"</span> %><br /><br /><%@ Import Namespace=<span class="str">"MVCJqueryDemo.Models"</span> %><br /><br /><asp:Content ID=<span class="str">"Content1"</span> ContentPlaceHolderID=<span class="str">"TitleContent"</span> runat=<span class="str">"server"</span>><br /><br /> Products<br /></asp:Content><br /><asp:Content ID=<span class="str">"Content2"</span> ContentPlaceHolderID=<span class="str">"MainContent"</span> runat=<span class="str">"server"</span>><br /> <h2><br /> Products</h2><br /> <form id=<span class="str">"searchForm"</span> action=<span class="str">"javascript:void();"</span>><br /> <input type=<span class="str">"text"</span> name=<span class="str">"name"</span> id=<span class="str">"searchBox"</span> /><br /> </form><br /> <div id=<span class="str">"products"</span> <span class="kwrd">class</span>=<span class="str">"productsDiv"</span>><br /> <%Html.RenderPartial(<span class="str">"ProductsPartial"</span>, <span class="kwrd">this</span>.Model); %><br /> </div><br /></asp:Content><br /></pre><br /><br />It has a form with a textbox, and then it has a div where we call RenderPartial to render a partial view called: ProductsPartial. Here's the code for the ProductsPartial.ascx:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><%@ Control Language=<span class="str">"C#"</span> Inherits=<span class="str">"System.Web.Mvc.ViewUserControl<IEnumerable<Product>>"</span> %><br /><%@ Import Namespace=<span class="str">"MVCJqueryDemo.Models"</span> %><br /><br /><br /> <table id=<span class="str">"productsTable"</span>><br /> <tr><br /> <th>Product ID</th><br /> <th>Product Name</th><br /> <th>Units <span class="kwrd">in</span> Stock</th><br /> <th>Unit Price</th><br /> <th>Being Produced</th><br /> <th>Units on Order</th><br /> </tr><br /> <%<span class="kwrd">foreach</span> (var product <span class="kwrd">in</span> <span class="kwrd">this</span>.Model)%><br /> <%{%><br /> <tr><br /> <td><%=product.ProductID %></td><br /> <td><%=product.ProductName %></td><br /> <td><%=product.UnitsInStock %></td><br /> <td><%=product.UnitPrice.Value.ToString(<span class="str">"$#0.00"</span>)%></td><br /> <td><img <span class="kwrd">class</span>=<span class="str">"inStockImages"</span> src=<span class="str">"<%=product.Discontinued ? "</span>../../Content/x.png<span class="str">" : "</span>../../Content/check.png<span class="str">" %>"</span> /></td><br /> <td><%=product.UnitsOnOrder %></td><br /> </tr> <br /> <%}%><br /> </table><br /></pre><br /><br />So basically, what's happening is this. When you go to ../Home/Products, the Products Action gets called on the Home controller. Then, we get a list of Products from the database, and pass that on to the Products View. The Products View then passes that on to the ProductsPartial which actually renders the products in a nice HTML table. <br /><br />At this point, we haven't done anything fancy yet. If we were to run it at this point, you'd see a list of all the products displayed. If you were to type anything in the textbox, nothing would happen. Here's where we want to start using some AJAX. The idea will be, that whenever the keyup event will be triggered in the textbox, we'll fire off an AJAX call to the server, and display the results. So first, let's look at the second Action in the Home Controller:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> [AcceptVerbs(HttpVerbs.Post)]<br /> <span class="kwrd">public</span> ActionResult Search(<span class="kwrd">string</span> name)<br /> {<br /> <span class="kwrd">using</span> (var repository = <span class="kwrd">new</span> NorthwindRepository(CONNECTIONSTRING))<br /> {<br /> var result = repository.GetProductsByName(name);<br /> <span class="kwrd">return</span> View(<span class="str">"ProductsPartial"</span>, result);<br /> }<br /> }<br /> }<br /></pre><br /><br />As you can see, this Action only accepts HTTP POST requests. Again, we call our repository, and get back a list of Products that match the search criteria. We then call return View to display the ProductsPartial, and we pass in the list of products.<br /><br />That's all very nice, but how do we call this method? How do we hook up an event to our textbox to trigger this method to be called? This is where we'll use jQuery to make the AJAX call. First, in the head section of your master page, you need to add these lines:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <script src=<span class="str">"../../Scripts/jquery-1.3.2.js"</span> type=<span class="str">"text/javascript"</span>></script><br /> <script src=<span class="str">"../../Scripts/jquery-1.3.2.min.js"</span> type=<span class="str">"text/javascript"</span>></script></pre><br /><br />This will include the jQuery libraries in your page. Then, I've added another file called ProductScripts.js into the Scripts folder. Then, I added this line to the head of my page:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <script src=<span class="str">"../../Scripts/ProductScripts.js"</span> type=<span class="str">"text/javascript"</span>></script></pre><br /><br />Here's what the ProductScripts.js file looks like:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br />$(document).ready(function() {<br /> $(<span class="str">"#searchBox"</span>).keyup(function(item) {<br /> var textValue = $(<span class="str">"#searchBox"</span>)[0].<span class="kwrd">value</span>;<br /> var form = $(<span class="str">"#searchForm"</span>).serialize();<br /> $.post(<span class="str">"/Home/Search"</span>, form, function(returnHtml) {<br /> $(<span class="str">"#products"</span>).html(returnHtml);<br /> });<br /><br /> });<br />});</pre><br /><br />Looks a little weird at first, but I'll try to explain. First we call $(document.ready(..)). In here is where we hook up all of our jQuery events. This ready function gets called as soon as the DOM is loaded. Then, we get a reference to the searchBox using $("#searchBox"). This is the equivalent of document.getElementById(..) in JavaScript. We then hook into the keyup event and whenever that event is triggered we call this function:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> var textValue = $(<span class="str">"#searchBox"</span>)[0].<span class="kwrd">value</span>;<br /> var form = $(<span class="str">"#searchForm"</span>).serialize();<br /> $.post(<span class="str">"/Home/Search"</span>, form, function(returnHtml) {<br /> $(<span class="str">"#products"</span>).html(returnHtml);<br /></pre><br /><br />First, we get the text that was typed into the textbox. Then, we get the entire form (which in this case is just the textbox itself). We then serialize the form and call the post method. This is where the actual AJAX call is happening. <a href="http://docs.jquery.com/Ajax/jQuery.post">The parameters that are passed into the post method</a> are as follows:<br /><br />URL : in our case it's /Home/Search<br />Data: in our case it's the serialized form, which will then get sent as a parameter to our Search Action on the Home Controller<br />Callback: in our case it's a function that we use to set the inner HTML of the products div. Remember, the Search Action in our controller renders the ProductsPartial View. So basically it send HTML back to the browesr as a result of the AJAX request. We take that HTML, and stick it into the Products div. <br /><br />The full source code is available at the link posted at the top, download it and mess with it. It's actually real simple, and real powerful.<br /><br />In this post I only demonstrated how to send back HTML. Another very common way of sending data is through JSON. I'll cover that in another post. ASP.NET MVC makes it EXTREMELY easy to send JSON across the wire.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com0tag:blogger.com,1999:blog-5611706923356552090.post-57265799287658216932009-06-29T10:20:00.007-04:002009-07-02T10:47:36.566-04:00Factory Pattern with Attributes. Get rid of the ugly switch / case.<span style="font-weight:bold;">Source Code:</span> <a href="http://www.box.net/shared/2yh2r6l91c">http://www.box.net/shared/2yh2r6l91c</a><br /><br />A very common design pattern used in Object Oriented Programming, is the Factory Pattern. The purpose of this post isn't to explain the factory pattern or why it's useful, rather I want to show a simple way to eliminate a giant switch / case found in many factory pattern implementations. For some good reading on the Factory Pattern, I suggest reading these two articles:<br /><br />Wikipedia : <a href="http://en.wikipedia.org/wiki/Factory_method_pattern">http://en.wikipedia.org/wiki/Factory_method_pattern</a><br /><br />MSDN : <a href="http://msdn.microsoft.com/en-us/library/ms954600.aspx">http://msdn.microsoft.com/en-us/library/ms954600.aspx</a><br /><br />To demonstrate a simple example of the Factory Pattern, I've created a few classes. First, I created a base Vehicle class that looks something like this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">abstract</span> <span class="kwrd">class</span> Vehicle<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> TopSpeed<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> 150;<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">abstract</span> <span class="kwrd">int</span> Wheels<br /> {<br /> get;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> ToString()<br /> {<br /> <span class="kwrd">return</span> String.Format(<span class="str">"A {0} has {1} wheels, and a top speed of {2} MPH."</span><br /> , <span class="kwrd">this</span>.GetType().Name, <span class="kwrd">this</span>.Wheels, <span class="kwrd">this</span>.TopSpeed);<br /> }<br /> }</pre><br /><br />Just a base class that has one virtual property, one abstract property, and it overrides ToString. Then, I've created 4 subclasses:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Car : Vehicle<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">int</span> Wheels<br /> {<br /> get { <span class="kwrd">return</span> 4; }<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> SuperCar : Car<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">int</span> TopSpeed<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> 200;<br /> }<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Truck : Vehicle<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">int</span> Wheels<br /> {<br /> get { <span class="kwrd">return</span> 18; }<br /> }<br /> }<br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Motorcycle : Vehicle<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">int</span> Wheels<br /> {<br /> get { <span class="kwrd">return</span> 2; }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">int</span> TopSpeed<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> 190;<br /> }<br /> }<br /> }<br /></pre><br /><br />So we have Vehicle, Car, SuperCar, Truck and Motorcycle. Now, say we wanted to create a Factory that returns us the correct Vehicle class based on an enum that we'd supply. So let's create an enum:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">enum</span> VehicleType<br /> {<br /> Car,<br /> SuperCar,<br /> Truck,<br /> Motorcyle<br /> }</pre><br /><br />We'd then have a method that looks something like this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> Vehicle GetVehicle(VehicleType vehicle)<br /> {<br /> <span class="kwrd">switch</span> (vehicle)<br /> {<br /> <span class="kwrd">case</span> VehicleType.Car:<br /> <span class="kwrd">return</span> <span class="kwrd">new</span> Car();<br /> <span class="kwrd">case</span> VehicleType.SuperCar:<br /> <span class="kwrd">return</span> <span class="kwrd">new</span> SuperCar();<br /> <span class="kwrd">case</span> VehicleType.Truck:<br /> <span class="kwrd">return</span> <span class="kwrd">new</span> Truck();<br /> <span class="kwrd">case</span> VehicleType.Motorcyle:<br /> <span class="kwrd">return</span> <span class="kwrd">new</span> Motorcycle();<br /> <span class="kwrd">default</span>:<br /> <span class="kwrd">return</span> <span class="kwrd">null</span>;<br /> }<br /> }<br /></pre><br />Well, this is all nice, and works fine, but imagine a scenario where you may have many many subclasses. This switch statement would get huge, and unmaintainable quickly. Imagine then that new subclasses come along, you'd have to first update the enum, and then remember to update this switch / case. Well, I think there's a better way to do this.<br /><br />The premise is simple; create an attribute that has one property called Type. This attribute will go on the enum, and will represent which type should be instantiated for each value of the enum. So, let's first create the Attribute class:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> VehicleInfoAttribute : Attribute<br /> {<br /> <span class="kwrd">private</span> Type type;<br /><br /> <span class="kwrd">public</span> VehicleInfoAttribute(Type type)<br /> {<br /> <span class="kwrd">this</span>.type = type;<br /> }<br /><br /> <span class="kwrd">public</span> Type Type<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.type;<br /> }<br /> }<br /> }<br /></pre><br /><br />Nothing fancy, just a simple attribute that will house the Type to be created. Now, let's go back to our enum, and decorate the values with the correct attributes:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">enum</span> VehicleType<br /> {<br /> [VehicleInfo(<span class="kwrd">typeof</span>(Car))]<br /> Car,<br /><br /> [VehicleInfo(<span class="kwrd">typeof</span>(SuperCar))]<br /> SuperCar,<br /><br /> [VehicleInfo(<span class="kwrd">typeof</span>(Truck))]<br /> Truck,<br /><br /> [VehicleInfo(<span class="kwrd">typeof</span>(Motorcycle))]<br /> Motorcyle<br /> }<br /></pre><br /><br />Now, each enum has an attribute that tells us which type to be instantiated for that type. Now, the fun part. The reflection bit in the factory method itself:<br /><br />First, I've created an extension method for enum's that helps with getting custom attributes off of enum values:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> Extensions<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> T GetAttribute<T>(<span class="kwrd">this</span> Enum enumValue)<br /> <span class="kwrd">where</span> T : Attribute<br /> {<br /> FieldInfo field = enumValue.GetType().GetField(enumValue.ToString());<br /> <span class="kwrd">object</span>[] attribs = field.GetCustomAttributes(<span class="kwrd">typeof</span>(T), <span class="kwrd">false</span>);<br /> T result = <span class="kwrd">default</span>(T);<br /><br /> <span class="kwrd">if</span> (attribs.Length > 0)<br /> {<br /> result = attribs[0] <span class="kwrd">as</span> T;<br /> }<br /><br /> <span class="kwrd">return</span> result;<br /> }<br /> }<br /></pre><br /><br />This allows you to do something like this:<br /><br />MyCustomAttribute a = myEnumValue.GetAttribute<MyCustomAttribute>();<br /><br />Now, we have all the pieces in place to write the Factory Method:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> Vehicle GetVehicle(VehicleType vehicle)<br /> {<br /> var vehicleAttribute = vehicle.GetAttribute<VehicleInfoAttribute>();<br /> <span class="kwrd">if</span> (vehicleAttribute == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">null</span>;<br /> }<br /><br /> var type = vehicleAttribute.Type;<br /> Vehicle result = Activator.CreateInstance(type) <span class="kwrd">as</span> Vehicle;<br /><br /> <span class="kwrd">return</span> result;<br /> }<br /></pre><br /><br />First we call our extension method to get the attribute value for the enum passed in. Then, we use the handy Activator.CreateInstance() to create an object of that type.<br /><br />To test it out, we can write a quick app:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">static</span> <span class="kwrd">void</span> Main()<br /> {<br /> Vehicle v = VehicleFactory.GetVehicle(VehicleType.Truck);<br /> Console.WriteLine(v);<br /> }<br /></pre><br /><br />This will output:<br /><br /><span style="font-weight:bold;">A Truck has 18 wheels, and a top speed of 150 MPH.</span><br /><br />Using this approach, yields two benefits. First, you no longer have a giant ugly switch / case. Secondly, if you ever have a case where another subclass is added, you just add another enum value (which you'd have to do anyway if you were using the switch / case), slap on the attribute, and you're done. The Factory method doesn't need to change at all.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com2tag:blogger.com,1999:blog-5611706923356552090.post-66668046036925197862009-06-23T10:25:00.005-04:002009-06-24T07:35:49.735-04:00LINQ Overkill. Why? Ha! Why not??<span style="font-weight:bold;">Source Code: </span> <a href="http://www.box.net/shared/tnt1569ql9">http://www.box.net/shared/tnt1569ql9</a><br /><br />Before going to SetFocus, we had to take a few test before being accepted. One of these tests was a simple coding exercise, which went something like this:<br /><blockquote><br />Write a program that accepts a string input from the user. Your program will then count the occurrence of each character in the string, and output the results in this format:<br /><br />There are 0 A's.<br />There are 2 B's.<br />There are 1 C's.<br />...<br />...</blockquote><br /><br />Simple program really, with a few easy approaches. I personally used a HashTable to hold the chars and the integers. After going through SetFocus, and learning about generics, I rewrote the app to use a Dictionary<char,int>, and the app basically looked something like this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> CountCharacters(<span class="kwrd">string</span> text)<br /> {<br /> Dictionary<<span class="kwrd">char</span>,<span class="kwrd">int</span>> chars = <span class="kwrd">new</span> Dictionary<<span class="kwrd">char</span>, <span class="kwrd">int</span>>();<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 65; i <= 90; i++) <span class="rem">//character integer values for 'A' - 'Z'</span><br /> {<br /> chars.Add((<span class="kwrd">char</span>)i, 0);<br /> }<br /><br /> <span class="kwrd">foreach</span> (var character <span class="kwrd">in</span> text.ToUpperInvariant())<br /> {<br /> <span class="kwrd">if</span> (chars.ContainsKey(character))<br /> {<br /> chars[character]++;<br /> }<br /> }<br /><br /> <span class="kwrd">foreach</span> (var kvp <span class="kwrd">in</span> chars)<br /> {<br /> Console.WriteLine(<span class="str">"There are {0} {1}'s."</span>, kvp.Value, kvp.Key);<br /> }<br /> }<br /></pre><br /><br />Basically, populate the dictionary with the alphabet in upper case, initialize all int's to zero's. Then, loop through the text, and increment the corresponding integer. Finally, loop through the dictionary, and output the results.<br /><br />Very nice. Recently however, I was bored one bight, and it hit me. Having used LINQ extensivley for quite a while now, I figured, I'm sure I can figure out a way to do this in a "LINQ one liner", ie. one gigantic impossible-to-understand LINQ statement. Why? Why not!!<br /><br />So, here's what I came up with. I'm warning you, it's isn't pretty but it works. I'll <b><i><u>try</u></i></b> my best to explain after:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> StringBuilder CountCharsAlexLinqMethod(<span class="kwrd">string</span> text)<br /> {<br /> var result = <span class="kwrd">new</span> StringBuilder();<br /> <span class="kwrd">foreach</span> (var item <span class="kwrd">in</span> (from p <span class="kwrd">in</span> <span class="str">"ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span><br /> join pa <span class="kwrd">in</span><br /> (from p <span class="kwrd">in</span> text.ToUpperInvariant()<br /> group p by p into g<br /> select <span class="kwrd">new</span> { Count = g.Count(), Character = g.Key })<br /> on p equals pa.Character into w<br /> from a <span class="kwrd">in</span> w.DefaultIfEmpty()<br /> select <span class="kwrd">new</span><br /> {<br /> Count = a == <span class="kwrd">null</span> ? 0 : a.Count,<br /> Character = p<br /> }))<br /> {<br /> result.AppendFormat(Format, item.Count, item.Character);<br /> }<br /><br /> <span class="kwrd">return</span> result;<br /> }<br /></pre><br /><br />Told you it wasn't pretty :) Ok, it looks worse than it is. The basic premise is as follows. First, let's analyze the inner query:<br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> (from p <span class="kwrd">in</span> text.ToUpperInvariant()<br /> group p by p into g<br /> select <span class="kwrd">new</span> { Count = g.Count(), Character = g.Key })</pre><br /><br />Think of this as a "GROUP BY" in SQL. It basically groups all the letters together in the given text, and counts them up. So at this point, if our text for example was the word "Hello", then this collection of anonymous objects would look something like this:<br /><br />{Character = 'H', Count = 1}<br />{Character = 'E', Count = 1}<br />{Character = 'L', Count = 2}<br />{Character = 'O', Count = 1}<br /><br />Once we have that, we basically do the equivalent of a LEFT OUTER JOIN on the entire alphabet. Since string implements IEnumerable<char> we can query it just like any other IEnumerable and even join on it. So what's happening is, we're joining our results from the inner query earlier, to a collection that contains the entire alphabet. Wherever they join, meaning wherever the letter is found in the inner query, use that as the count, if not, use 0 as the count:<br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> on p equals pa.Character into w<br /> from a <span class="kwrd">in</span> w.DefaultIfEmpty()<br /> select <span class="kwrd">new</span><br /> {<br /> Count = a == <span class="kwrd">null</span> ? 0 : a.Count,<br /> Character = p<br /> }))<br /></pre><br /><br />Crazy, but not too bad. Well, the story isn't over. Since I thought this was kinda neat, and I HAD to show someone, I decided to bug <a href="http://jamesarendt.typepad.com/">James Arendt</a> who was one of my instructors at Set Focus and I sent him my code. Here was his response:<br /><br /><blockquote>Fun solution, Alex! I don't use the group join too often so it was neat to see it in action on this solution. I decided to take a stab at the code as well, but I took a different direction.</blockquote><br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> CountCharacters(<span class="kwrd">string</span> text)<br /> {<br /> <span class="rem">// I could have used a literal, but I wanted to demonstrate some</span><br /> <span class="rem">// other LINQ routines.</span><br /> var letters = Enumerable.Range(<span class="str">'A'</span>, 26).Select(i => (<span class="kwrd">char</span>)i);<br /> var sourceChars = letters.Concat(text.ToUpperInvariant());<br /><br /> var results = from c <span class="kwrd">in</span> sourceChars<br /> group c by c into g<br /> <span class="kwrd">where</span> <span class="kwrd">char</span>.IsLetter(g.Key)<br /> orderby g.Key<br /> select <span class="kwrd">new</span> { Char = g.Key, Count = g.Count() - 1 };<br /><br /> <span class="kwrd">foreach</span> (var result <span class="kwrd">in</span> results)<br /> {<br /> Console.WriteLine(<span class="str">"There are {0} {1}'s."</span>, result.Count, result.Char);<br /> }<br /> }<br /></pre><br /><br />His approach is a little different. First, he builds up an enumerable with the alphabet without using literals (no real difference there). Then however, he tacks on the text to the end of that enumerable. So at this point, if our test text was "Hello", the enumerable would be:<br /><br />'A','B','C','D'.....'Z','H','E','L','L','O'.<br /><br />Then, he does a group by on this enumerable, counting up the duplicates.<br /><br />Nice. So, whenever you have more than one way of doing something, what does every computer nerd like me love to do? Why benchmark of course!!<br /><br />In my initial comparisons between my method and the way James did it, his way was quicker every time. I wrote back to him, and congratulated him that his way was in fact quicker, but he pointed out to me, that his way was only quicker with shorter strings. When the strings got really long, my way turned out to be fast. So, I decided to flesh this all out, and really benchmark all ways of doing it.<br /><br />Before I do that, just for the sake of really doing it in just one line, I wrote it one more way:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> StringBuilder CountCharsAlexLinqCompleteOverkill(<span class="kwrd">string</span> text)<br /> {<br /> var result = <span class="kwrd">new</span> StringBuilder();<br /><br /> (from p <span class="kwrd">in</span> <span class="str">"ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span><br /> join pa <span class="kwrd">in</span><br /> (from p <span class="kwrd">in</span> text.ToUpperInvariant()<br /> group p by p into g<br /> select <span class="kwrd">new</span> { Count = g.Count(), Character = g.Key })<br /> on p equals pa.Character into w<br /> from a <span class="kwrd">in</span> w.DefaultIfEmpty()<br /> select <span class="kwrd">new</span><br /> {<br /> Count = a == <span class="kwrd">null</span> ? 0 : a.Count,<br /> Character = p<br /> }).ForEach(item => result.AppendFormat(Format, item.Count, item.Character));<br /><br /> <span class="kwrd">return</span> result;<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> ForEach<T>(<span class="kwrd">this</span> IEnumerable<T> list, Action<T> action)<br /> {<br /> <span class="kwrd">foreach</span> (var item <span class="kwrd">in</span> list)<br /> {<br /> action(item);<br /> }<br /> }<br /></pre><br /><br />Not really THAT much different, but now it really is just one statement. There's a ForEach extension method now, so the actual CountCharacters method is just one big statement. So, here's the entire class I used for benchmarking:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Collections.Generic;<br /><span class="kwrd">using</span> System.Linq;<br /><span class="kwrd">using</span> System.Text;<br /><br /><span class="kwrd">namespace</span> LinqOverkill<br />{<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> CharacterCounter<br /> {<br /> <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">string</span> Format = <span class="str">"There are {0} {1}'s.\n"</span>;<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> StringBuilder CountCharsDictionaryMethod(<span class="kwrd">string</span> text)<br /> {<br /> var chars = <span class="kwrd">new</span> Dictionary<<span class="kwrd">char</span>, <span class="kwrd">int</span>>();<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 65; i <= 90; i++) <span class="rem">//character integer values for 'A' - 'Z'</span><br /> {<br /> chars.Add((<span class="kwrd">char</span>)i, 0);<br /> }<br /><br /> <span class="kwrd">foreach</span> (var character <span class="kwrd">in</span> text.ToUpperInvariant())<br /> {<br /> <span class="kwrd">if</span> (chars.ContainsKey(character))<br /> {<br /> chars[character]++;<br /> }<br /> }<br /><br /> var result = <span class="kwrd">new</span> StringBuilder();<br /><br /><br /> <span class="kwrd">foreach</span> (var kvp <span class="kwrd">in</span> chars)<br /> {<br /> result.AppendFormat(Format, kvp.Value, kvp.Key);<br /> }<br /><br /> <span class="kwrd">return</span> result;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> StringBuilder CountCharsAlexLinqMethod(<span class="kwrd">string</span> text)<br /> {<br /> var result = <span class="kwrd">new</span> StringBuilder();<br /> <span class="kwrd">foreach</span> (var item <span class="kwrd">in</span> (from p <span class="kwrd">in</span> <span class="str">"ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span><br /> join pa <span class="kwrd">in</span><br /> (from p <span class="kwrd">in</span> text.ToUpperInvariant()<br /> group p by p into g<br /> select <span class="kwrd">new</span> { Count = g.Count(), Character = g.Key })<br /> on p equals pa.Character into w<br /> from a <span class="kwrd">in</span> w.DefaultIfEmpty()<br /> select <span class="kwrd">new</span><br /> {<br /> Count = a == <span class="kwrd">null</span> ? 0 : a.Count,<br /> Character = p<br /> }))<br /> {<br /> result.AppendFormat(Format, item.Count, item.Character);<br /> }<br /><br /> <span class="kwrd">return</span> result;<br /> }<br /><br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> StringBuilder CountCharsJamesLinqMethod(<span class="kwrd">string</span> text)<br /> {<br /> var builder = <span class="kwrd">new</span> StringBuilder();<br /><br /> var letters = Enumerable.Range(<span class="str">'A'</span>, 26).Select(i => (<span class="kwrd">char</span>)i);<br /> var sourceChars = letters.Concat(text.ToUpperInvariant());<br /><br /> var results = from c <span class="kwrd">in</span> sourceChars<br /> group c by c into g<br /> <span class="kwrd">where</span> <span class="kwrd">char</span>.IsLetter(g.Key)<br /> orderby g.Key<br /> select <span class="kwrd">new</span> { Char = g.Key, Count = g.Count() - 1 };<br /><br /> <span class="kwrd">foreach</span> (var result <span class="kwrd">in</span> results)<br /> {<br /> builder.AppendFormat(Format, result.Count, result.Char);<br /> }<br /><br /> <span class="kwrd">return</span> builder;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> StringBuilder CountCharsAlexLinqCompleteOverkill(<span class="kwrd">string</span> text)<br /> {<br /> var result = <span class="kwrd">new</span> StringBuilder();<br /><br /> (from p <span class="kwrd">in</span> <span class="str">"ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span><br /> join pa <span class="kwrd">in</span><br /> (from p <span class="kwrd">in</span> text.ToUpperInvariant()<br /> group p by p into g<br /> select <span class="kwrd">new</span> { Count = g.Count(), Character = g.Key })<br /> on p equals pa.Character into w<br /> from a <span class="kwrd">in</span> w.DefaultIfEmpty()<br /> select <span class="kwrd">new</span><br /> {<br /> Count = a == <span class="kwrd">null</span> ? 0 : a.Count,<br /> Character = p<br /> }).ForEach(item => result.AppendFormat(Format, item.Count, item.Character));<br /><br /> <span class="kwrd">return</span> result;<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> ForEach<T>(<span class="kwrd">this</span> IEnumerable<T> list, Action<T> action)<br /> {<br /> <span class="kwrd">foreach</span> (var item <span class="kwrd">in</span> list)<br /> {<br /> action(item);<br /> }<br /> }<br /> }<br />}<br /></pre><br /><br />I then wrote a test method which tested it first with a short string of 24 characters, and then 4135 characters. Here's the main method:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Collections.Generic;<br /><span class="kwrd">using</span> System.Linq;<br /><span class="kwrd">using</span> System.Text;<br /><span class="kwrd">using</span> System.Diagnostics;<br /><br /><span class="kwrd">namespace</span> LinqOverkill<br />{<br /> <span class="kwrd">class</span> Program<br /> {<br /> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)<br /> {<br /> <span class="kwrd">string</span> text = <span class="str">"This is some dummy text."</span>;<br /> <span class="kwrd">int</span> iterations = 10000;<br /><br /> BenchmarhMethods(text, iterations);<br /><br /> <span class="kwrd">string</span> bigText = LinqOverkill.Resource.BigText;<br /> BenchmarhMethods(bigText, iterations);<br /><br /> Console.ReadKey(<span class="kwrd">true</span>);<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> BenchmarhMethods(<span class="kwrd">string</span> text, <span class="kwrd">int</span> iterations)<br /> {<br /> Console.WriteLine(<span class="str">"Testing with {0} characters."</span>, text.Length);<br /> Stopwatch watch = <span class="kwrd">new</span> Stopwatch();<br /><br /> watch.Start();<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 1; i <= iterations; i++)<br /> {<br /> CharacterCounter.CountCharsDictionaryMethod(text);<br /> }<br /> watch.Stop();<br /> Console.WriteLine(<span class="str">"Dictionary method took: {0} milliseconds."</span>, watch.ElapsedMilliseconds);<br /><br /> watch.Reset();<br /><br /> watch.Start();<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 1; i <= iterations; i++)<br /> {<br /> CharacterCounter.CountCharsAlexLinqMethod(text);<br /> }<br /> watch.Stop();<br /> Console.WriteLine(<span class="str">"Alex LINQ method took: {0} milliseconds."</span>, watch.ElapsedMilliseconds);<br /><br /> watch.Reset();<br /><br /> watch.Start();<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 1; i <= iterations; i++)<br /> {<br /> CharacterCounter.CountCharsAlexLinqCompleteOverkill(text);<br /> }<br /> watch.Stop();<br /> Console.WriteLine(<span class="str">"Alex Overkill method took: {0} milliseconds."</span>, watch.ElapsedMilliseconds);<br /><br /> watch.Reset();<br /><br /> watch.Start();<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 1; i <= iterations; i++)<br /> {<br /> CharacterCounter.CountCharsJamesLinqMethod(text);<br /> }<br /> watch.Stop();<br /> Console.WriteLine(<span class="str">"James LINQ method took: {0} milliseconds."</span>, watch.ElapsedMilliseconds);<br /><br /> watch.Reset();<br /> Console.WriteLine();<br /> }<br /> }<br />}<br /></pre><br /><br />Here were the results on my machine:<br /><br />Testing with 24 characters.<br />Dictionary method took: 427 milliseconds.<br />Alex LINQ method took: 1176 milliseconds.<br />Alex Overkill method took: 1157 milliseconds.<br />James LINQ method took: 636 milliseconds.<br /><br />Testing with 4135 characters.<br />Dictionary method took: 7484 milliseconds.<br />Alex LINQ method took: 6417 milliseconds.<br />Alex Overkill method took: 6429 milliseconds.<br />James LINQ method took: 6738 milliseconds.<br /><br />As you can see, with 24 characters, using a Dictionary and looping yourself is the quickest way. Second quickest is the way James did it. Then, my way (the Alex LINQ and the overkill are basically the same exact thing) came in last.<br /><br />When I pumped it up to 4135 characters though, my was fast fastest :) Even faster than using a Dictionary. <br /><br />One final note. In production code, this really isn't a good idea. Yes, it's loads of fun to do, (I love doin stuff like this) but if another developer, or even you really, ever needs to go back to look at this code, it'll take them 3 times as long to figure out what's going on and how it's doing it. <br /><br />Finally, I'll leave you with this example of the worst abuse of LINQ ever. It's awesome, but I have no clue what the heck it's doing!!<a href="http://blogs.msdn.com/lukeh/archive/2007/10/01/taking-linq-to-objects-to-extremes-a-fully-linqified-raytracer.aspx"> http://blogs.msdn.com/lukeh/archive/2007/10/01/taking-linq-to-objects-to-extremes-a-fully-linqified-raytracer.aspx</a>A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com0tag:blogger.com,1999:blog-5611706923356552090.post-49467844812420680692009-06-19T13:59:00.005-04:002009-06-19T15:25:29.569-04:00C# Html Screen Scraping Part 2 / Performing POST with Cookies<span style="font-weight:bold;">Source code:</span> <a href="http://www.box.net/shared/r7u052y507">http://www.box.net/shared/r7u052y507</a><br /><span style="font-weight:bold;"><br />I just want to point out, that I purposely didn't break this out into separate classes and methods, and I know I'm duplicating ALOT of code. I simply wanted to demonstrate each technique on its own.</span><br /><br /><a href="http://crazorsharp.blogspot.com/2009/06/c-html-screen-scraping-part-1.html">In my previous post</a>, I demonstrated how to connect to a website, and download the HTML (aka Screen Scraping). That all works nicely if it's a simple site you need to connect to. Sometimes however, you can't simply connect to the site and download the HTML, rather you need to first login, or maybe you need to enter some kind of search term first into a text box. In the HTML world, generally the page will have a simple form that posts to the server which queries the database or something based on the info supplied in the post, and then dynamically builds up the page. How do you do that in your C# app? How do you pass the values on to the Form Post that the server is expecting?<br /><br />Throughout this post, I'll be referring to the code that's attached to this post. It basically has two projects. One's a simple ASP.NET MVC website, and the other is a winforms app. In order to run this properly, you'll need to first launch the web app, and then launch the windows app. Here's a simple screen shot of what the windows app looks like so you can get an idea:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/832476_formpost-screenshot.jpg"></img><br /><br /><span style="font-weight: bold;">First, a little note. In order to demonstrate this, I needed a site that had a simple Form with cookies. Since I couldn't find anything that was really simple and that would be easy to demo, I decided to create my own little "Website". It's written in ASP.NET MVC, so if you want to be able to run the code sample supplied in the link, head over to the <a href="http://www.asp.net/mvc/download/">ASP.NET MVC Website and download it</a> (if you don't already have it.)</span><br /><br />The site basically has two URL's that are of interest. The first is ../Home/SimplePost. If you navigate to that page, you'll see a simple textbox with a button. When you click the button, it simply posts the text in the textbox back to the server, and then it just outputs it back to the browser. Here's the HTML rendered for that form:<br /><br /><form action="/Home/SimplePost" method="post"><br /> <input type="text" id="text" name="text" /><br /> <input type="submit" value="submit" /><br /></form><br /><br />The Form will Post to a site on the server /Home/SimplePost. We also can see in the form, that the server is expecting a parameter that's called "text". It's safe to assume, that anything with an input field (except for the button) is needed by the server. So, now we have enough info to write our C# function:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> PostWithoutCookies()<br /> {<br /> HttpWebRequest request = (HttpWebRequest)WebRequest.Create(<br>String.Format(<span class="str">"http://localhost:{0}/Home/SimplePost"</span>, port));<br /> request.Method = <span class="str">"POST"</span>;<br /> request.ContentType = <span class="str">"application/x-www-form-urlencoded"</span>;<br /> <span class="kwrd">string</span> postData = String.Format(<span class="str">"text={0}"</span>, String.IsNullOrEmpty(textBoxPost.Text)<br /> ? <span class="str">"somerandomemail@address.com"</span> : <span class="kwrd">this</span>.textBoxPost.Text);<br /> <span class="kwrd">byte</span>[] bytes = Encoding.UTF8.GetBytes(postData);<br /> request.ContentLength = bytes.Length;<br /><br /> Stream requestStream = request.GetRequestStream();<br /> requestStream.Write(bytes, 0, bytes.Length);<br /><br /> WebResponse response = request.GetResponse();<br /> Stream stream = response.GetResponseStream();<br /> StreamReader reader = <span class="kwrd">new</span> StreamReader(stream);<br /> stream.Dispose();<br /> reader.Dispose();<br /> <span class="kwrd">this</span>.richTextBox1.Text = reader.ReadToEnd();<br /> }<br /></pre><br /><br />(This is all part of the app that's attached at the top of this post. It basically outputs all the results to a richtextbox.)<br /><br />A bit more complicated than last time, but not as bad. The main difference here is that we'll actually be writing TO the Request stream. This will insert the form values into the headers, which will allow the server to receive this data and process it. The trick is that for each value that you need to add, you use this syntax:<br /><br />field1=value1&field2=value2&field3=value3<br /><br />where field is the name of the input field, and the value is the value you want to send over to the server (ie. the text that would be entered into the textbox). <br /><br />So if we were to run this method now, we'd see the text that we posted to the server (the text that was in the textbox of the app) in the richtextbox.<br /><br />There is one more thing that we can do with this. Very often, in order to access certain areas of a site, you need to first log in. When you login, the server sends a cookie to the browser, and then for each subsequent request that is for authenticated users only, the browser send the cookie back to the server so that you can access those parts of the site. Here, we're acting like a browser, so we need to have the ability to get the cookie, retain it somehow, and then pass that on to the next request.<br /><br />To demonstrate this, in the web app of this demo, there's a page called "..Home/PostWithCookie". When you access this page, it sends a cookie to the browser. Then, on that page there's a form identical to the first one. When you post back to the server though, it checks if the cookie is there. If it is, it outputs "Cookie Found" along with the cookie value, if not, it outputs "Cookie not found." <br /><br />So back in our Windows App, we need a way to first access that first page that gets us our cookie, then we need to GET the cookie, and finally we need to pass the cookie on with the form post. Here's the code:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">private</span> CookieCollection GetCookies()<br /> {<br /> HttpWebRequest request = (HttpWebRequest)WebRequest.Create(<br>String.Format(<span class="str">"http://localhost:{0}/Home/PostWithCookie"</span>, port));<br /> request.CookieContainer = <span class="kwrd">new</span> CookieContainer();<br /> HttpWebResponse response = (HttpWebResponse)request.GetResponse();<br /> Stream responseStream = response.GetResponseStream();<br /> <span class="kwrd">return</span> response.Cookies;<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> PostWithCookies()<br /> {<br /> CookieCollection cookies = <span class="kwrd">this</span>.GetCookies();<br /> var request = (HttpWebRequest)WebRequest.Create(<br>String.Format(<span class="str">"http://localhost:{0}/Home/PostWithCookie"</span>, port));<br /> request.CookieContainer = <span class="kwrd">new</span> CookieContainer();<br /> request.Method = <span class="str">"POST"</span>;<br /> request.ContentType = <span class="str">"application/x-www-form-urlencoded"</span>;<br /> <span class="kwrd">string</span> postData = String.Format(<span class="str">"text={0}"</span>, String.IsNullOrEmpty(textBoxPost.Text)<br /> ? <span class="str">"somerandomemail@address.com"</span> : <span class="kwrd">this</span>.textBoxPost.Text);<br /> <span class="kwrd">byte</span>[] bytes = Encoding.UTF8.GetBytes(postData);<br /> request.ContentLength = bytes.Length;<br /> <span class="kwrd">if</span> (cookies != <span class="kwrd">null</span>)<br /> {<br /> request.CookieContainer.Add(cookies);<br /> }<br /><br /> Stream requestStream = request.GetRequestStream();<br /> requestStream.Write(bytes, 0, bytes.Length);<br /><br /> var response = request.GetResponse();<br /> var stream = response.GetResponseStream();<br /> var reader = <span class="kwrd">new</span> StreamReader(stream);<br /> <span class="kwrd">this</span>.richTextBox1.Text = reader.ReadToEnd();<br /> }<br /></pre><br /><br />The first bit of code, the GetCookies method looks JUST like the original Screen Scrape method, however here we're actually grabbing the cookies. The trick is to new up a new <a href="http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.cookiecontainer.aspx">CookieContainer </a>before we do the request. Once we have a container, and we execute the request, we can get the cookies out of the response.<br /><br />Now we have the cookie, but we aren't done. We want to pass this cookie back to the server when we post to the form. The only difference again here is that we have to new up a CookieContainer on the request, and add the cookies to that container. Once it's there, when you execute the POST, the cookies will get sent over as well.<br /><br />The only way to really understand this all, is to download the sample, and mess with it. It's not very complicated, but you need to just mess with it a bit to understand. Once you do grasp it though, you'll see just how powerful this is. You can access many websites straight from within your app, and get the data right into your application.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com1tag:blogger.com,1999:blog-5611706923356552090.post-49685505832745444042009-06-19T13:14:00.005-04:002009-06-19T13:57:12.434-04:00C# Html Screen Scraping Part 1This is the first post of a two part series. <br /><br /><span style="font-weight:bold;">Source Code:</span> <a href="http://www.box.net/shared/i2p7t9kxkt">http://www.box.net/shared/i2p7t9kxkt</a><br /><br />Very often, when a particular website has some information you'd like to use in your application, you'd see if they have some kind of API which you can use to query their data. However, it's very common for a website either to not have an API altogether, or not have that little bit of info you need made available in their API. What's done generally to get around this is a technique knows as "<a href="http://en.wikipedia.org/wiki/Screen_scraping#Screen_scraping">Screen Scarping</a>". (Screen Scraping is a general term, not just for the web, but for the purpose of this blog, when I say Screen Scarping, I mean HTML Screen Scraping). <br /><br />The general gist of it is this: when a browser contacts a site, an HTML document is sent back to the browser. The browser then has the (tedious) task of parsing out that HTML and rendering it out to the screen. End of the day though, the HTML is just a text file. What screen scraping basically is, you write an app that "acts" like a web browser, meaning it contacts the web site, downloads the HTML file into memory, at which point you're free to parse it out any which way you like and extract the data you need. In .NET this is incredibly easy to do, and I'll demonstrate a simple sample:<br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">private</span> <span class="kwrd">string</span> GetWebsiteHtml(<span class="kwrd">string</span> url)<br /> {<br /> WebRequest request = WebRequest.Create(url);<br /> WebResponse response = request.GetResponse();<br /> Stream stream = response.GetResponseStream();<br /> StreamReader reader = <span class="kwrd">new</span> StreamReader(stream);<br /> <span class="kwrd">string</span> result = reader.ReadToEnd();<br /> stream.Dispose();<br /> reader.Dispose();<br /> <span class="kwrd">return</span> result;<br /> }<br /></pre><br /><br />Yup, that's pretty much it. First, you create a WebRequest object with the given URL. Then, you get a Response object out of that Request. Finally you get the response stream and read it with a StreamReader. <br /><br />I attached a simple app so you can give it a whirl. Basically, it's a simple windows app with a textbox and a button. Enter any url in the textbox (make sure to write the full url including http://....) and hit the Go button. That will get you the entire HTML of that site, and display it in the richtextbox.<br /><br />This is obviously a rough sample, make sure to add proper error handling, but other than that, it's pretty straightforward and real simple! The only thing to watch out for when scraping, is that your parsing code will rely on the HTML being formatted a VERY specific way. If the site changes in any way, your code WILL break.<br /><br />This was a very simple post; in the next post, I'll take this much further, and demonstrate how we can actually POST to a server, and even get the cookies.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com1tag:blogger.com,1999:blog-5611706923356552090.post-1979209188005537522009-06-15T14:54:00.005-04:002010-05-24T16:37:41.518-04:00INotifyPropertyChanged - How to and when to?<span style="font-weight:bold;">Source Code:</span> <a href="http://www.box.net/shared/nx8uj1rm1b">http://www.box.net/shared/nx8uj1rm1b<br /></a><br />Databinding has always been fascinating to me; at first it really all looks like magic, how controls just track changes, and keep everything in sync. So much so, that very often I try to use it as little as possible, because I don't like using things I don't fully understand how they work. However, it does often save you from a lot of extra code, so I think it's very useful to explore it a bit, in particular the <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx">INotifyPropertyChanged </a>interface.<br /><br />Let's first start with a quick demo. Say you have a class, let's call is MyClass:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> MyClass<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">int</span> MyProperty { get; set; }<br /> }<br /></pre><br /><br />Now let's say we have a Windows Form that has a DataGridView that we're using to bind to a BindingList of this type:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> BindingList<MyClass> bindingList = <span class="kwrd">new</span> BindingList<MyClass>();<br /> <span class="kwrd">private</span> <span class="kwrd">void</span> Bind()<br /> {<br /> bindingList.Add(<span class="kwrd">new</span> MyClass { MyProperty = 10 });<br /> bindingList.Add(<span class="kwrd">new</span> MyClass { MyProperty = 20 });<br /> bindingList.Add(<span class="kwrd">new</span> MyClass { MyProperty = 30 });<br /> bindingList.Add(<span class="kwrd">new</span> MyClass { MyProperty = 40 });<br /> <span class="kwrd">this</span>.dataGridView1.DataSource = bindingList;<br /> }<br /></pre><br /><br />This will work, and you'll have a DataGridView with one column called MyProperty with the rows 10,20,30,40. Very nice. Suppose however, that somewhere in the application, the contents of this list change (new values from database, or user input updated data, whatever..). You'll notice, that if your code applies changes directly to the BindingList, it will NOT reflect in the DataGridView:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> UpdateList()<br /> {<br /> <span class="kwrd">foreach</span> (MyClass mc <span class="kwrd">in</span> <span class="kwrd">this</span>.bindingList)<br /> {<br /> mc.MyProperty = 100;<br /> }<br /> }<br /></pre><br /><br />Just some simple code that changes all the MyProperty's to 100. You'll notice that these changes will NOT be reflected in the DataGridView. Well, the question becomes, how then do we have the changes reflected in the DataGridView? You COULD set the DataGridView's datasource to null and then rebind, but that's hacky and clumsy.<br /><br />Enter the INotifyPropertyChanged interface. The interface has one property on it, and it's actually an event:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">interface</span> INotifyPropertyChanged<br /> {<br /> <span class="rem">// Summary:</span><br /> <span class="rem">// Occurs when a property value changes.</span><br /> <span class="kwrd">event</span> PropertyChangedEventHandler PropertyChanged;<br /> }<br /></pre><br /><br />Looks quite simple, let's implement this now properly with a Person class. I've attached the source code to this post so you can download it and see for yourself. Here's the entire Person class:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Person : INotifyPropertyChanged<br /> {<br /><br /> <span class="kwrd">private</span> <span class="kwrd">string</span> firstName;<br /> <span class="kwrd">private</span> <span class="kwrd">string</span> lastName;<br /> <span class="kwrd">private</span> <span class="kwrd">int</span> age;<br /><br /> <span class="kwrd">public</span> Person(<span class="kwrd">string</span> firstName, <span class="kwrd">string</span> lastName, <span class="kwrd">int</span> age)<br /> {<br /> <span class="kwrd">this</span>.firstName = firstName;<br /> <span class="kwrd">this</span>.lastName = lastName;<br /> <span class="kwrd">this</span>.age = age;<br /> }<br /><br /> <span class="kwrd">public</span> Person()<br /> {<br /><br /> }<br /><br /> <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> OnPropretyChanged(<span class="kwrd">string</span> propertyName)<br /> {<br /> var handler = <span class="kwrd">this</span>.PropertyChanged;<br /> <span class="kwrd">if</span> (handler != <span class="kwrd">null</span>)<br /> {<br /> handler(<span class="kwrd">this</span>, <span class="kwrd">new</span> PropertyChangedEventArgs(propertyName));<br /> }<br /> }<br /><br /><br /> <span class="kwrd">public</span> <span class="kwrd">string</span> FirstName<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.firstName;<br /> }<br /> set<br /> {<br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.firstName != <span class="kwrd">value</span>)<br /> {<br /> <span class="kwrd">this</span>.firstName = <span class="kwrd">value</span>;<br /> <span class="kwrd">this</span>.OnPropretyChanged(<span class="str">"FirstName"</span>);<br /> }<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">string</span> LastName<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.lastName;<br /> }<br /> set<br /> {<br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.lastName != <span class="kwrd">value</span>)<br /> {<br /> <span class="kwrd">this</span>.lastName = <span class="kwrd">value</span>;<br /> <span class="kwrd">this</span>.OnPropretyChanged(<span class="str">"LastName"</span>);<br /> }<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">int</span> Age<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.age;<br /> }<br /> set<br /> {<br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.age != <span class="kwrd">value</span>)<br /> {<br /> <span class="kwrd">this</span>.age = <span class="kwrd">value</span>;<br /> <span class="kwrd">this</span>.OnPropretyChanged(<span class="str">"Age"</span>);<br /> }<br /> }<br /> }<br /><br /> <span class="preproc">#region</span> INotifyPropertyChanged<br /><br /> <span class="kwrd">public</span> <span class="kwrd">event</span> PropertyChangedEventHandler PropertyChanged;<br /><br /> <span class="preproc">#endregion</span><br /> }<br /></pre><br /><br />The first thing you'll notice is that I implemented INotifyPropertyChanged. Then, in each setter of the properties, I call a method called "OnPRopertyChanged" which actually raises the event. The only downside of this, is that you can't use auto properties because the setters need to have logic. Also, since we'll be raising an event every time the value changes, it's worth putting in the extra if check:<br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.firstName != <span class="kwrd">value</span>)<br /> {<br /> <span class="kwrd">this</span>.firstName = <span class="kwrd">value</span>;<br /> <span class="kwrd">this</span>.OnPropretyChanged(<span class="str">"FirstName"</span>);<br /> }<br /></pre><br /><br />just to make sure that the value actually changed. <br /><br />I then created a simple Form that has a DataGridView that's bound to a BindingList<Person>. It also has a button, that when clicked, adds 5 years to everyones age. <br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> Form1 : Form<br /> {<br /><br /> <span class="kwrd">private</span> BindingList<Person> people;<br /><br /> <span class="kwrd">public</span> Form1()<br /> {<br /> InitializeComponent();<br /> <span class="kwrd">this</span>.people = <span class="kwrd">new</span> BindingList<Person>();<br /> <span class="kwrd">this</span>.PopulatePeople();<br /> <span class="kwrd">this</span>.dataGridView1.DataSource = people;<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> PopulatePeople()<br /> {<br /> <span class="kwrd">this</span>.people.Add(<span class="kwrd">new</span> Person(<span class="str">"Alex"</span>, <span class="str">"Friedman"</span>, 27));<br /> <span class="kwrd">this</span>.people.Add(<span class="kwrd">new</span> Person(<span class="str">"Jack"</span>, <span class="str">"Bauer"</span>, 45));<br /> <span class="kwrd">this</span>.people.Add(<span class="kwrd">new</span> Person(<span class="str">"Tony"</span>, <span class="str">"Almeda"</span>, 39));<br /> <span class="kwrd">this</span>.people.Add(<span class="kwrd">new</span> Person(<span class="str">"Chloe"</span>, <span class="str">"O'Brien"</span>, 37));<br /> <span class="kwrd">this</span>.people.Add(<span class="kwrd">new</span> Person(<span class="str">"Bill"</span>, <span class="str">"Buchanan"</span>, 50));<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> ChangeAges()<br /> {<br /> <span class="kwrd">foreach</span> (Person p <span class="kwrd">in</span> <span class="kwrd">this</span>.people)<br /> {<br /> p.Age += 5;<br /> }<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> buttonChange_Click(<span class="kwrd">object</span> sender, EventArgs e)<br /> {<br /> <span class="kwrd">this</span>.ChangeAges();<br /> }<br /> }<br /></pre><br /><br />If you run this, you'll notice that DataGridView does in fact get updated, even though I just manipulated the underlying list. I never actually touch the DataGridView itself. Internally, the BindingList checks to see if the class of type T (remember, BindingList is generic) implements INotfiyPropertyChanged. If it does, it hooks into that event, and when the event is raised, it updates itself.<br /><br />The one thing to be careful is that when raising this event, you actually hardcode the name of the property. Personally, I wish there was a better way, but anything I've seen online so far had some serious overhead (like using the StackFrame to figure out which property is changing) so if someone knows of a better way, please let me know!<br /><br /><span style="font-weight:bold;">UPDATE: </span>I recently blogged about a better approach to dealing with the INotifyPropertyChanged event that takes care of the hardcoded strings issue. <a href="http://crazorsharp.blogspot.com/2010/05/inotifypropertychanged-without-magic.html">Check it out here.</a>A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com1tag:blogger.com,1999:blog-5611706923356552090.post-70571378440743408392009-06-11T15:35:00.005-04:002010-02-08T12:31:49.759-05:00Tweaking a DataGridView ComboBoxColumn to allow editing.Let me first say this. I love the DataGridView and I think it's an awesome and very versatile control. It's highly customizable, and you can create a damn near excel-like application around it. Having said that though, anyone who's ever used a DataGridView knows just how "quirky" the stupid thing can be. Things that look like they should be simple, require clever hacks to implement.<br /><br />Recently, I was creating an in-house app here at work, in which I needed a DataGridView with a ComboBoxColumn but with one wrinkle. Out of the box, the ComboBoxColumn doesn't support editing. Meaning, it acts like a ComboBox that has the DropDownStyle set to DropDownList (which doesn't allow the user to enter new values). We, however, did need to have the ability for the user to enter new values. I thought that this would be a simple property that I'd be able to set on the ComboBoxColumn. Yea, well there is no such property, so queue clever hack! <br /><br />The first thing you need to do is hook into the DataGridView's <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.editingcontrolshowing.aspx">EditingControlShowing </a>event. This event fires when the actual ComboBox is "dropped down". The interesting thing is that the EventArgs has a property on it "Control" that can be cast to a standard WinForms ComboBox. <br /><br />To demonstrate, I've created a simple Windows App that has a button on it and a DataGridView. It also has a method that just returns a list of strings that contains all the days of the week (needed something just for testing). When the button is clicked, the DataGridView gets populated with a ComboBoxColumn with all the days. Here's the entire code:<br /><div style="overflow:scroll;"><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Collections.Generic;<br /><span class="kwrd">using</span> System.ComponentModel;<br /><span class="kwrd">using</span> System.Windows.Forms;<br /><br /><span class="kwrd">namespace</span> DataGridViewComboBoxTesting<br />{<br /> <span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> Form1 : Form<br /> {<br /> <span class="kwrd">public</span> Form1()<br /> {<br /> InitializeComponent();<br /> <span class="kwrd">this</span>.dataGridView1.EditingControlShowing += HandleEditShowing;<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> HandleEditShowing(<span class="kwrd">object</span> sender, DataGridViewEditingControlShowingEventArgs e)<br /> {<br /> var cbo = e.Control <span class="kwrd">as</span> ComboBox;<br /> <span class="kwrd">if</span> (cbo == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">return</span>;<br /> }<br /><br /> cbo.DropDownStyle = ComboBoxStyle.DropDown;<br /> cbo.Validating -= HandleComboBoxValidating;<br /> cbo.Validating += HandleComboBoxValidating;<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> HandleComboBoxValidating(<span class="kwrd">object</span> sender, CancelEventArgs e)<br /> {<br /> var combo = sender <span class="kwrd">as</span> DataGridViewComboBoxEditingControl;<br /> <span class="kwrd">if</span> (combo == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">return</span>;<br /> }<br /> <span class="kwrd">if</span> (!combo.Items.Contains(combo.Text)) <span class="rem">//check if item is already in drop down, if not, add it to all</span><br /> {<br /> var comboColumn = <span class="kwrd">this</span>.dataGridView1.Columns[<span class="kwrd">this</span>.dataGridView1.CurrentCell.ColumnIndex]<br> <span class="kwrd">as</span> DataGridViewComboBoxColumn;<br /> combo.Items.Add(combo.Text);<br /> comboColumn.Items.Add(combo.Text);<br /> <span class="kwrd">this</span>.dataGridView1.CurrentCell.Value = combo.Text;<br /> }<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> button1_Click(<span class="kwrd">object</span> sender, EventArgs e)<br /> {<br /> var cboColumn = <span class="kwrd">new</span> DataGridViewComboBoxColumn<br /> {<br /> Name = <span class="str">"ComboBox"</span>,<br /> HeaderText = <span class="str">"Combo Box Column"</span><br /> };<br /><br /> <span class="kwrd">foreach</span> (var day <span class="kwrd">in</span> <span class="kwrd">this</span>.GetListOfStrings())<br /> {<br /> cboColumn.Items.Add(day);<br /> }<br /><br /> <span class="kwrd">this</span>.dataGridView1.Columns.Add(cboColumn);<br /> }<br /><br /> <span class="kwrd">public</span> IEnumerable<<span class="kwrd">string</span>> GetListOfStrings()<br /> {<br /> <span class="kwrd">foreach</span> (var day <span class="kwrd">in</span> Enum.GetValues(<span class="kwrd">typeof</span>(DayOfWeek)))<br /> {<br /> <span class="kwrd">yield</span> <span class="kwrd">return</span> day.ToString();<br /> }<br /> }<br /> }<br />}<br /></pre><br /></div><br />As you can see, in the HandleEditShowing method, we can get access the the underlying ComboBox itself, and set the DropDownStyle property right there. We then do a little more hackery so that when the user enters a new value, we can add it to all other ComboBox's in that column. We do that by hooking into the ComboBox's Validating event (first we unhook it in case we're already hooked into it, so that our event handler doesn't get called more than once).<br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> HandleEditShowing(<span class="kwrd">object</span> sender, DataGridViewEditingControlShowingEventArgs e)<br /> {<br /> var cbo = e.Control <span class="kwrd">as</span> ComboBox;<br /> <span class="kwrd">if</span> (cbo == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">return</span>;<br /> }<br /><br /> cbo.DropDownStyle = ComboBoxStyle.DropDown;<br /> cbo.Validating -= HandleComboBoxValidating;<br /> cbo.Validating += HandleComboBoxValidating;<br /> }<br /></pre><br /><br />The event handler then looks like this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> HandleComboBoxValidating(<span class="kwrd">object</span> sender, CancelEventArgs e)<br /> {<br /> var combo = sender <span class="kwrd">as</span> DataGridViewComboBoxEditingControl;<br /> <span class="kwrd">if</span> (combo == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">return</span>;<br /> }<br /> <span class="kwrd">if</span> (!combo.Items.Contains(combo.Text)) <span class="rem">//check if item is already in drop down, if not, add it to all</span><br /> {<br /> var comboColumn = <span class="kwrd">this</span>.dataGridView1.Columns[<span class="kwrd">this</span>.dataGridView1.CurrentCell.ColumnIndex] <span class="kwrd">as</span> DataGridViewComboBoxColumn;<br /> combo.Items.Add(combo.Text);<br /> comboColumn.Items.Add(combo.Text);<br /> <span class="kwrd">this</span>.dataGridView1.CurrentCell.Value = combo.Text;<br /> }<br /> }<br /></pre><br /><br />Simple. We just check if it's already in the list, if it's not then add it to the combo box as well as add it to all other combo boxes. <br /><br />Here's a link to the source code. In the code I also created a class called DataGridViewComboBoxColumnEx which basically inherits from DataGridViewComboBoxColumn and encapsulates all this hackery nicely. You just use it as you normally would but it allows editing.<br /><br />Source code: <a href="http://www.box.net/shared/73bmzmv1r6">http://www.box.net/shared/73bmzmv1r6</a>A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com6tag:blogger.com,1999:blog-5611706923356552090.post-52170224440853296602009-06-09T16:14:00.005-04:002009-06-09T16:57:47.690-04:00How do closures / captured variables work under the hood?<span style="font-weight:bold;">First, a little disclaimer. I'll be using 3.0 syntax with Lambda's but this has been around since .NET 2.0 and anonymous methods.</span><br /><br />Ok, so first a little demonstration:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">namespace</span> ClosureDemo<br />{<br /> <span class="kwrd">public</span> <span class="kwrd">delegate</span> <span class="kwrd">void</span> StuffDoer();<br /><br /> <span class="kwrd">class</span> Program<br /> {<br /> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)<br /> {<br /> var stuffDoerDelegate = GetDelegate();<br /> stuffDoerDelegate();<br /> stuffDoerDelegate();<br /><br /> Console.ReadKey(<span class="kwrd">true</span>);<br /><br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> StuffDoer GetDelegate()<br /> {<br /> <span class="kwrd">int</span> counter = 1;<br /> StuffDoer result = () =><br /> {<br /> counter++;<br /> Console.WriteLine(counter);<br /> };<br /> result();<br /> <span class="kwrd">return</span> result;<br /> }<br /><br /> }<br />}<br /></pre><br /><br />Simple little app. First, I create a delegate type called "StuffDoer" that has a return type of void, and takes no parameters. Then, I have a private method that news up a StuffDoer delegate, and attaches an anonymous method to it. Here's the interesting thing to note though: I declared a variable called counter <span style="font-style:italic;">outside of the anonymous method</span>. The obvious question that comes to mind is how? Shouldn't counter be outside of scope? If you didn't declare this as an anonymous method, but rather as a concrete method:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> StuffDoer GetDelegate()<br /> {<br /> <span class="kwrd">int</span> counter = 1;<br /> StuffDoer result = <span class="kwrd">new</span> StuffDoer(DoStuff);<br /> <span class="kwrd">return</span> result;<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> DoStuff()<br /> {<br /> counter++;<br /> Console.WriteLine(counter);<br /> }<br /></pre><br /><br />This obviously wouldn't compile because counter is undefined in the DoStuff method. So how can it work in the anonymous method? Furthermore, you'll notice, that if you run this program, it prints out 2, 3 and 4 which shows us that the counter variable somehow stuck around?? How? We declared it once inside our GetDelegate method, shouldn't it have been lost after we left that method? How did it retain it's state?<br /><br />This is knows as "closures" or "captured variables" and was always just one of those "black magic it just works" kinda thing for me. I researched it, thought I kinda understood it, but never QUITE got it. Recently, however, I picked up a copy of <a href="http://www.amazon.com/C-Depth-What-need-master/dp/1933988363">Jon Skeet's C# In Depth</a> book (I CANNOT stress enough how great this book is! I'm only halfway through, didn't even start with the C# 3.0 / .NET 3.5 stuff yet, and already I've learned tons of stuff. I HIGHLY recommend it!) and it opened my eyes as to what exactly is going on under the covers. I'll admit, it may not really matter at the end of the day, you could just stick with the "it just works" attitude, but I like trying to understand how stuff works under the covers.<br /><br />The first thing to understand is that the compiler is smart. Very smart. It notices that the counter variable is being "captured" and does some funky stuff for us. If you open reflector, you can see what exactly happened here:<br /><br /><img src="http://www.biggerbids.com/members/images/13047/public/818782_reflector-closure.jpg"><br /><br />You'll notice that there's a class there that I never created. You'll see it there as "<>c__DisplayClass1". And if you look at the code, it looks something like this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br />[CompilerGenerated]<br /><span class="kwrd">private</span> <span class="kwrd">sealed</span> <span class="kwrd">class</span> <>c__DisplayClass1<br />{<br /> <span class="rem">// Fields</span><br /> <span class="kwrd">public</span> <span class="kwrd">int</span> counter;<br /><br /> <span class="rem">// Methods</span><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> <GetDelegate>b__0()<br /> {<br /> <span class="kwrd">this</span>.counter++;<br /> Console.WriteLine(<span class="kwrd">this</span>.counter);<br /> }<br />}<br /><br /></pre><br /><br />Ok, we're getting somewhere; a class was created for us with the counter variable as a public member, as well as a public method that looks just like our anonymous method. Very cool.....but how exactly does that help us? Now, if we look back in our "GetDelegate" method in Reflector, this is what we see:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> StuffDoer GetDelegate()<br /> {<br /> <>c__DisplayClass1 CS$<>8__locals2 = <span class="kwrd">new</span> <>c__DisplayClass1();<br /> CS$<>8__locals2.counter = 1;<br /> StuffDoer result = <span class="kwrd">new</span> StuffDoer(CS$<>8__locals2.<GetDelegate>b__0);<br /> result();<br /> <span class="kwrd">return</span> result;<br /> }<br /></pre><br /><br />Looks like a mess with all the compiler generated stuff, but we can finally see the big picture. I'll rewrite the code in "plain english" so you can see what's going on:<br /><br />First, I create a counter class: (this is instead of the "<>c__DisplayClass1" the compiler generated.)<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> CounterClass<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">int</span> counter;<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> DoSomething()<br /> {<br /> counter++;<br /> Console.WriteLine(counter);<br /> }<br /> }<br /></pre><br /><br />Then, back in the Program.cs, let's change the GetDelegate method to this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> StuffDoer GetDelegate()<br /> {<br /> CounterClass c1 = <span class="kwrd">new</span> CounterClass();<br /> c1.counter = 1;<br /> StuffDoer result = <span class="kwrd">new</span> StuffDoer(c1.DoSomething);<br /> result();<br /> <span class="kwrd">return</span> result;<br /> }<br /></pre><br /><br />Here's the key. As I've <a href="http://crazorsharp.blogspot.com/2009/03/net-memory-leaks-it-is-possible.html">pointed out in the past</a>, delegates are objects, and can hold references to other objects. So, what's happening here is, an instance of our CounterClass is created, and we pass in one of it's methods to a new instance of the StuffDoer delegate. This now causes the delegate to hold a reference to this CounterClass object. Then, every time after that, when you invoke the delegate, it's still holding a reference to the <span style="font-style:italic;">same object it had in the beginning</span> so you're constantly calling the methods on the same object! <br /><br />Now it all makes sense; that's how it can reference the counter variable inside the anonymous method, because it's actually a method in a class that's referencing it's own public member. And now also we understand how it maintains state, because it's just a regular object that's being kept around. Smart smart compiler :)A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com0tag:blogger.com,1999:blog-5611706923356552090.post-83268132868647773092009-06-03T22:39:00.005-04:002009-06-03T23:47:17.300-04:00Lesson learned....RTFM!A few weeks ago, I was tasked with writing a <a href="http://www.sitemaps.org/protocol.php">site map</a> generator for our new site at work that uses ASP.NET MVC. When using ASP.NET MVC Controllers have "Actions" that map to URL's. For the sake of this blog point, all that's important to know is that generally Actions are methods that return an ActionResult object. So, the idea was, in order to generate the site map correctly, I would use reflection to inspect the entire assembly, and any method that returned an ActionResult would be entered into the site map with the correct XML.<br /><br />The catch however was that in many instances, the return type of our Action's weren't actually ActionResult objects, but rather classes the <span style="font-style: italic;">derived </span>from ActionResult. (Some that are built into ASP.NET MVC and some custom ones.) So, I quickly realized I needed a method that you can pass in a type, along with another type, and the method would tell you if anywhere up the inheritance chain, type1 inherits from type2.<br /><br />My first thought was "Perfect! I'll just use recursion!" This quickly got me excited, because it's not every day you get to use recursion in a useful piece of production code, much less when it came to reflection. So, I ended up writing an extension method that crawls up the inheritance chain recursively and it worked perfectly. Here's the code:<br /><pre class="csharpcode"><br /><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> TypeExtensions<br />{<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> InheritsFrom(<span class="kwrd">this</span> Type type, Type baseType)<br /> {<br /> <span class="kwrd">if</span> (baseType == <span class="kwrd">null</span> || type == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">false</span>;<br /> }<br /><br /> <span class="kwrd">if</span> (type.BaseType == baseType)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">true</span>;<br /> }<br /><br /> <span class="kwrd">return</span> type.BaseType.InheritsFrom(baseType);<br /> }<br />}<br /><br /><br /></pre>Basically, the Type class has a handy property called BaseType which basically gives you the BaseType (duh!). If the Type is object, then BaseType is null, in which case we know we've reached the top of the inheritance chain, and we're done. To test this method out, let's whip up some demo code:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> MyMemoryStreamBase : MemoryStream<br /> {<br /><br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> MyMemoryStreamChild : MyMemoryStreamBase<br /> {<br /><br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> MyMemoryStreamGrandChild : MyMemoryStreamChild<br /> {<br /><br /> }<br /></pre>Basically, I've created a nice Inheritance chain that goes up to MemoryStream -> Stream -> MarshalByRefObject and finally object. Here's how you can test it:<br /><br /><pre class="csharpcode"><br /> Type type = <span class="kwrd">typeof</span>(MyMemoryStreamGrandChild);<br /> <span class="kwrd">bool</span> result = type.InheritsFrom(<span class="kwrd">typeof</span>(MarshalByRefObject));<br /> Console.WriteLine(result);<br /></pre><br />If you run this, the result will be True, proving that my cute little method worked, and I was all happy.<br /><br />Fast forward a few weeks, and while browsing StackOverflow, I came across a question regarding reflection and BaseType's when some dude posts a link to this:<br /><br /><a href="http://msdn.microsoft.com/en-us/library/system.type.issubclassof.aspx">Type.IsSubClassOf(..)</a><br /><br /><span style="font-weight: bold;">Yeah, that's right! It's built right into the .NET Framework!</span> Now obviously it's impossible to know of every method in the framework, but as soon as I thought of the need, and that it involved recursion, I simply whipped out Visual Studio and started coding, without actually taking a moment and thinking, hey research this first! You can't be the FIRST person to come across this very issue!<br /><br />Feeling completely beat, I was just curious at this point as to how it's implemented in the Framework. Were they also using recursion, or did they have some other ingenious way of doing this. Well here's how they did it:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">bool</span> IsSubclassOf(Type c)<br />{<br /> Type baseType = <span class="kwrd">this</span>;<br /> <span class="kwrd">if</span> (baseType != c)<br /> {<br /> <span class="kwrd">while</span> (baseType != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">if</span> (baseType == c)<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">true</span>;<br /> }<br /> baseType = baseType.BaseType;<br /> }<br /> <span class="kwrd">return</span> <span class="kwrd">false</span>;<br /> }<br /> <span class="kwrd">return</span> <span class="kwrd">false</span>;<br />}<br /></pre><br />Yea, no recursion, just a simple while loop. At this point, I was just curious in general as to which method is quicker. So, some quick benchmarks:<br /><br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> CompareMethodsSpeed()<br /> {<br /> Stopwatch watch = <span class="kwrd">new</span> Stopwatch();<br /> Type type = <span class="kwrd">typeof</span>(MyMemoryStreamGrandChild);<br /> Type baseType = <span class="kwrd">typeof</span>(MarshalByRefObject);<br /> watch.Start();<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i < 100000; i++)<br /> {<br /> type.InheritsFrom(baseType);<br /> }<br /> watch.Stop();<br /> Console.WriteLine(<span class="str">"My way took: {0} ticks."</span>, watch.ElapsedTicks);<br /><br /> watch.Reset();<br /><br /> watch.Start();<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i < 100000; i++)<br /> {<br /> type.IsSubclassOf(baseType);<br /> }<br /> watch.Stop();<br /> Console.WriteLine(<span class="str">"Their way took: {0} ticks."</span>, watch.ElapsedTicks);<br /> }<br /></pre><br /><br />Then I ran this one my machine and the results were:<br /><br />My way took: 107433 ticks.<br />Their way took: 41684 ticks.<br /><br />So yea, I got my butt whooped!! I'll chalk this one up to experience.<br /><br />Moral of the story? Two things. First, not just because you CAN do it with recursion, does that mean you SHOULD do it that way. Second, RTFM!! Chances are, MS has more time to test various ways of doing certain things, so double check that something is in the Framework before rolling your own.<br /><br />The only one thing I'll say in my (somewhat weak) defense is that InheritsFrom is a MUCH better name for this method than IsSubslassOf IMO. So yea, name your methods better MS!!A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com3tag:blogger.com,1999:blog-5611706923356552090.post-29357834121648632012009-06-02T10:06:00.005-04:002009-06-11T15:03:11.372-04:00Creating a Splash Screen in .NET with a progress bar.<span style="font-weight:bold;">EDIT:</span> I've added a link to the source code: <a href="http://www.box.net/shared/xbo9xvlguu">http://www.box.net/shared/xbo9xvlguu</a><br /><br />Many times an application needs to do many time consuming operations at start-up. Sometimes you need to read data from a database, sometimes you may need to retrieve some data from a web service. When this happens, it's often useful to display a "Splash Screen" to the user, with a company logo or something, along with a progress bar to indicate how much longer it will take for the app to load. While it may sound simple at first, it can be a bit tricky; if you simply show a screen, and do your time consuming operations, your UI will hang and your progress bar will never update. Therefore, there's some threading involved (not too much, don't get scared!), so I'll demonstrate a simple example here.<br /><br />Start off by creating a simple Windows Forms project. Once it's loaded, add another windows form (besides for the Form1 that's already there) and call it "SplashScreen". To get the look and feel right, let's set some properties:<br /><br /><ul><li>FormBorderStyle: None</li><li>TopMost : True</li><li>StartPosition: CenterScreen</li></ul>Now, in the properties window, find the BackgroundImage property and click the little elipsis {...} and select a picture from your hard drive. I also then changed the BackgroundImageLayout property to None but you can do whatever you want. Then, add a progress bar to the bottom of the form, and set the Dock property to Bottom. Here's what my splash screen looks like in the designer: (not sure why I chose a Halo picture....)<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.biggerbids.com/members/images/13047/public/807564_splashscreen.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 584px; height: 472px;" src="http://www.biggerbids.com/members/images/13047/public/807564_splashscreen.jpg" alt="" border="0" /></a>Now, we need to give access to someone outside of this class to update the progress (the progressBar is a private member and can't be accessed.) Here's the problem; if we simply wrap the progress bar's Value property in our own getter/setter like this:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">int</span> Progress<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">this</span>.progressBar1.Value;<br /> }<br /> set<br /> {<br /> <span class="kwrd">this</span>.progressBar1.Value = <span class="kwrd">value</span>;<br /> }<br /> }<br /><br /></pre>while you can do that, remember, this splash screen will be shown in a seperate thread. If you then try to access this property from your main thread, you'll get an InvalidOperationException that "Cross-thread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on." So, in order to be able to set any of the UI elements from another thread, we need to call the form's Invoke method which takes a delegate. Here's the complete code for the SplashScreen class:<br /><br /><pre class="csharpcode"><br /><span class="kwrd">using</span> System.Windows.Forms;<br /><br /><span class="kwrd">namespace</span> SplashScreenTesting<br />{<br /> <span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> SplashScreen : Form<br /> {<br /> <span class="kwrd">private</span> <span class="kwrd">delegate</span> <span class="kwrd">void</span> ProgressDelegate(<span class="kwrd">int</span> progress);<br /><br /> <span class="kwrd">private</span> ProgressDelegate del;<br /> <span class="kwrd">public</span> SplashScreen()<br /> {<br /> InitializeComponent();<br /> <span class="kwrd">this</span>.progressBar1.Maximum = 100;<br /> del = <span class="kwrd">this</span>.UpdateProgressInternal;<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> UpdateProgressInternal(<span class="kwrd">int</span> progress)<br /> {<br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.Handle == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">return</span>;<br /> }<br /><br /> <span class="kwrd">this</span>.progressBar1.Value = progress;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> UpdateProgress(<span class="kwrd">int</span> progress)<br /> {<br /> <span class="kwrd">this</span>.Invoke(del, progress);<br /> }<br /> }<br />}<br /></pre><br />As you can see, we created a delegate that we'll use to invoke the update to the progress bar. (The reason why I have a null check for this.Handle is because I was getting an exception right at the start up that the Handle wasn't created yet.)<br /><br />Ok, now let's create a class that simulates a time consuming operation. Basically, it just calculates Math.Pow for numbers 1 - 100 raised to the 1 - 500,000th power. Every time we move on to another outer number (the 1 - 100) we raise an event that reports progress. Once it's done, we raise an event that we're done. Here's the complete class:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Collections.Generic;<br /><span class="kwrd">using</span> System.Linq;<br /><span class="kwrd">using</span> System.Text;<br /><br /><span class="kwrd">namespace</span> SplashScreenTesting<br />{<br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Hardworker<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">event</span> EventHandler<HardWorkerEventArgs> ProgressChanged;<br /> <span class="kwrd">public</span> <span class="kwrd">event</span> EventHandler HardWorkDone;<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> DoHardWork()<br /> {<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 1; i <= 100; i++)<br /> {<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> j = 1; j <= 500000; j++)<br /> {<br /> Math.Pow(i, j);<br /> }<br /> <span class="kwrd">this</span>.OnProgressChanged(i);<br /> }<br /><br /> <span class="kwrd">this</span>.OnHardWorkDone();<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> OnProgressChanged(<span class="kwrd">int</span> progress)<br /> {<br /> var handler = <span class="kwrd">this</span>.ProgressChanged;<br /> <span class="kwrd">if</span> (handler != <span class="kwrd">null</span>)<br /> {<br /> handler(<span class="kwrd">this</span>, <span class="kwrd">new</span> HardWorkerEventArgs(progress));<br /> }<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> OnHardWorkDone()<br /> {<br /> var handler = <span class="kwrd">this</span>.HardWorkDone;<br /> <span class="kwrd">if</span> (handler != <span class="kwrd">null</span>)<br /> {<br /> handler(<span class="kwrd">this</span>, EventArgs.Empty);<br /> }<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> HardWorkerEventArgs : EventArgs<br /> {<br /> <span class="kwrd">public</span> HardWorkerEventArgs(<span class="kwrd">int</span> progress)<br /> {<br /> <span class="kwrd">this</span>.Progress = progress;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">int</span> Progress<br /> {<br /> get;<br /> <span class="kwrd">private</span> set;<br /> }<br /> }<br />}<br /></pre><br /><br />I also created a custom event args so that we can pass the progress on to the subscriber of our ProgressChanged event. (As a side note, if you're wondering about the strange assignement taking place when raising the event, see <a href="http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx">Eric Lippert's blog on the subject.</a>)<br /><br />Now, on to the main part of the app; the displaying of the splash screen. In the Form1's load event, we'll spawn off another thread to actually display the splash screen and then on the main thread we'll do our "Hard Work". Once the HardWorker has reported that the progress is complete, we'll dispose of the splashscreen and display the main Form. Here's the code, I'll try my best to explain:<br /><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 class="csharpcode"><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Windows.Forms;<br /><span class="kwrd">using</span> System.Threading;<br /><br /><span class="kwrd">namespace</span> SplashScreenTesting<br />{<br /><span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> Form1 : Form<br />{<br /> <span class="kwrd">private</span> SplashScreen splashScreen;<br /> <span class="kwrd">private</span> <span class="kwrd">bool</span> done = <span class="kwrd">false</span>;<br /> <span class="kwrd">public</span> Form1()<br /> {<br /> InitializeComponent();<br /> <span class="kwrd">this</span>.Load += <span class="kwrd">new</span> EventHandler(HandleFormLoad);<br /> <span class="kwrd">this</span>.splashScreen = <span class="kwrd">new</span> SplashScreen();<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> HandleFormLoad(<span class="kwrd">object</span> sender, EventArgs e)<br /> {<br /> <span class="kwrd">this</span>.Hide();<br /><br /> Thread thread = <span class="kwrd">new</span> Thread(<span class="kwrd">new</span> ThreadStart(<span class="kwrd">this</span>.ShowSplashScreen));<br /> thread.Start();<br /><br /> Hardworker worker = <span class="kwrd">new</span> Hardworker();<br /> worker.ProgressChanged += (o, ex) =><br /> {<br /> <span class="kwrd">this</span>.splashScreen.UpdateProgress(ex.Progress);<br /> };<br /><br /> worker.HardWorkDone += (o, ex) =><br /> {<br /> done = <span class="kwrd">true</span>;<br /> <span class="kwrd">this</span>.Show();<br /> };<br /><br /> worker.DoHardWork();<br /> }<br /><br /><br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> ShowSplashScreen()<br /> {<br /> splashScreen.Show();<br /> <span class="kwrd">while</span> (!done)<br /> {<br /> Application.DoEvents();<br /> }<br /> splashScreen.Close();<br /> <span class="kwrd">this</span>.splashScreen.Dispose();<br /> }<br />}<br />}</pre></div><br />In the constructor we just hook into the Load event and new up the SplashScreen. Then, in the Load event handler, we first hide the current form, because we don't want that to be seen just yet. We then create a Thread and pass in a delegate to our ShowSplashScreen method. The show splash screen method is what's actually going to be run on a seperate thread. First, it displays the SplashScreen. Then, it just sits there in a constant loop waiting for the "done" bool to be set to true. The key ingredient here is the call to Application.Doevents(). I think Microsoft does a good job explaining what this does so I'll let them do that talking:<br /><br /><blockquote><p>When you run a Windows Form, it creates the new form, which then waits for events to handle. Each time the form handles an event, it processes all the code associated with that event. All other events wait in the queue. While your code handles the event, your application does not respond. For example, the window does not repaint if another window is dragged on top.</p><p>If you call <span><span class="selflink">DoEvents</span></span> in your code, your application can handle the other events. For example, if you have a form that adds data to a <span><a id="ctl00_MTContentSelector1_mainContentContainer_ctl24" onclick="javascript:Track('ctl00_MTContentSelector1_mainContentContainer_cpe336716_c|ctl00_MTContentSelector1_mainContentContainer_ctl24',this);" href="http://msdn.microsoft.com/en-us/library/system.windows.forms.listbox.aspx">ListBox</a></span> and add <span><span class="selflink">DoEvents</span></span> to your code, your form repaints when another window is dragged over it. If you remove <span><span class="selflink">DoEvents</span></span> from your code, your form will not repaint until the click event handler of the button is finished executing. For more information on messaging, see <span><a id="ctl00_MTContentSelector1_mainContentContainer_ctl25" onclick="javascript:Track('ctl00_MTContentSelector1_mainContentContainer_cpe336716_c|ctl00_MTContentSelector1_mainContentContainer_ctl25',this);" href="http://msdn.microsoft.com/en-us/library/ms171532.aspx">User Input in Windows Forms</a></span>.<br /></p><p></p><br /></blockquote>Basically, it allows other events to be taken care of, even though the current procedure is blocking execution. This allows our progress bar to be updated.<br /><br />Back in the form load, we then new up our HardWorker and hook into it's events. (I'm using the more terse Lambda syntax, <a href="http://crazorsharp.blogspot.com/2009/03/new-features-in-c-30-net-35-part-2.html">see my previous blog post on the subject here for more information</a>.) Basically, every time the HardWorker reports progress, we update our progress bar. Then when it's done, we set our done flag to true, and show the main form. Finally, we actually kick it off with a call to DoHardWork();<br /><br />Try it out and run it. It's actually kinda neat to see it in action. This is obviously a very rough example, but it should give you a basic idea on how to get this done.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com9tag:blogger.com,1999:blog-5611706923356552090.post-58645809501820417902009-05-24T21:44:00.006-04:002009-06-11T16:47:50.064-04:00When KeyPressed / KeyDown just isn't enough. An adventure in GetKeyboardState.<span style="font-weight:bold;">Source Code:</span> <a href="http://www.box.net/shared/y7v5jskfd1">http://www.box.net/shared/y7v5jskfd1</a><br /><br />A question on <a href="http://stackoverflow.com/questions/902767/c-tetris-clone-cant-get-block-to-respond-properly-to-arrow-key-combinations">StackOverflow</a> this weekend, piqued my interest. It was about some guy that was creating a Tetris game in C# (using Winforms) and was having issues with keyboard input. Basically, he was hooking into the Forms KeyDown event, and if the key was either left down or right, he'd move the tetris piece accordingly. The problem he was running into was if the user would hold down more than one key at a time (which is very common when playing Tetris or any other game for that matter), only one key would register.<br /><br />Having messed with XNA in the past (I still hope to release a game to the XBOX Community games in this life time :-P ), I had a hunch. In XNA, things work a little different. A little background on how games work in general. All games consist of a "Game Loop". Basically, the entire application runs in one gigantic loop. You have a timer that constantly runs in the background, and every time the timer "ticks" two things happen. Update() is called, and Draw() is called. During the update routine, you update your game logic, ie: move player's position, move enemies position etc.. Then, during the Draw routine, you draw everything to screen.<br /><br />It is during this Update routine, where you "poll" the keyboard (or gamepad when working on the XBOX 360) to find out what's going on. Here's a small sample:<br /><br /><!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red0\green128\blue0;}??\fs20 \cf3 var\cf0 state = \cf4 Keyboard\cf0 .GetState();\par ?? \cf3 foreach\cf0 (\cf3 var\cf0 key \cf3 in\cf0 state.GetPressedKeys())\par ?? \{\par ?? \cf5 //do something\par ??\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;"> <!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 var\cf0 state = \cf4 Keyboard\cf0 .GetState();\par ?? \cf3 bool\cf0 downPressed = state.IsKeyDown(\cf4 Keys\cf0 .Down);\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;"> <p style="margin: 0px;"><span style="color: rgb(43, 145, 175);"> 56</span> <span style="color:blue;">var</span> state = <span style="color: rgb(43, 145, 175);">Keyboard</span>.GetState();</p> <p style="margin: 0px;"><span style="color: rgb(43, 145, 175);"> 57</span> <span style="color:blue;">bool</span> downPressed = state.IsKeyDown(<span style="color: rgb(43, 145, 175);">Keys</span>.Down);</p> </div> </div><br />As you can see, you "ask" the keyboard if the Down key is pressed at the current time. The cool thing about this method is that you can "ask" for multiple keys in one trip. There's nothing stopping you from doing this:<br /><br /><!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 var\cf0 state = \cf4 Keyboard\cf0 .GetState();\par ?? \cf3 bool\cf0 downPressed = state.IsKeyDown(\cf4 Keys\cf0 .Down);\par ?? \cf3 bool\cf0 upPressed = state.IsKeyDown(\cf4 Keys\cf0 .Up);} --> <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;"> <p style="margin: 0px;"><span style="color: rgb(43, 145, 175);"> 56</span> <span style="color:blue;">var</span> state = <span style="color: rgb(43, 145, 175);">Keyboard</span>.GetState();</p> <p style="margin: 0px;"><span style="color: rgb(43, 145, 175);"> 57</span> <span style="color:blue;">bool</span> downPressed = state.IsKeyDown(<span style="color: rgb(43, 145, 175);">Keys</span>.Down);</p> <p style="margin: 0px;"><span style="color: rgb(43, 145, 175);"> 58</span> <span style="color:blue;">bool</span> upPressed = state.IsKeyDown(<span style="color: rgb(43, 145, 175);">Keys</span>.Up);</p> </div><br /><br />In Windows Forms though, if you listen for the KeyDown event, the KeyEventArgs will give you the Keycode, but only of ONE key. So, if more than one key is pressed, what do you do?<br /><br />After some searching, I found that there's a "<a href="http://msdn.microsoft.com/en-us/library/ms646301%28VS.85%29.aspx">GetKeyboardState</a>" function that's part of the Win32 API. We should be able to P/Invoke this function, and poll the keyboard for more than one key. According to the Microsoft documentation, you pass in the int value of the key, and you get back a short. <blockquote></blockquote><blockquote><p>The return value specifies the status of the specified virtual key, as follows: </p><ul><li>If the high-order bit is 1, the key is down; otherwise, it is up.</li></ul><ul><li>If the low-order bit is 1, the key is toggled. A key, such as the CAPS LOCK key, is toggled if it is turned on. The key is off and untoggled if the low-order bit is 0. A toggle key's indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled.</li></ul></blockquote>So, I found <a href="http://sanity-free.org/17/obtaining_key_state_info_in_dotnet_csharp_getkeystate_implementation.html">this helpful little class online</a> that wraps this API call nicely.<br /><br />First, a simple struct to hold the Key's state:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">public</span> <span class="kwrd">struct</span> KeyStateInfo<br />{<br /> <span class="kwrd">private</span> Keys key;<br /> <span class="kwrd">private</span> <span class="kwrd">bool</span> isPressed;<br /> <span class="kwrd">private</span> <span class="kwrd">bool</span> isToggled;<br /><br /> <span class="kwrd">public</span> KeyStateInfo(Keys key, <span class="kwrd">bool</span> ispressed, <span class="kwrd">bool</span> istoggled)<br /> {<br /> <span class="kwrd">this</span>.key = key;<br /> isPressed = ispressed;<br /> isToggled = istoggled;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> KeyStateInfo Default<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> <span class="kwrd">new</span> KeyStateInfo(Keys.None, <span class="kwrd">false</span>, <span class="kwrd">false</span>);<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> Keys Key<br /> {<br /> get { <span class="kwrd">return</span> key; }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">bool</span> IsPressed<br /> {<br /> get { <span class="kwrd">return</span> isPressed; }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">bool</span> IsToggled<br /> {<br /> get { <span class="kwrd">return</span> isToggled; }<br /> }<br />}<br /></pre><br />Then, here's the actual class that wraps the P/Invoke:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Windows.Forms;<br /><span class="kwrd">using</span> System.Runtime.InteropServices;<br /><br /><span class="kwrd">public</span> <span class="kwrd">class</span> KeyboardInfo<br />{<br /> <span class="kwrd">private</span> KeyboardInfo() { }<br /> [DllImport(<span class="str">"user32"</span>)]<br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">extern</span> <span class="kwrd">short</span> GetKeyState(<span class="kwrd">int</span> vKey);<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> KeyStateInfo GetKeyState(Keys key)<br /> {<br /> <span class="kwrd">short</span> keyState = GetKeyState((<span class="kwrd">int</span>)key);<br /> <span class="kwrd">int</span> low = Low(keyState), high = High(keyState);<br /> <span class="kwrd">bool</span> toggled = low == 1;<br /> <span class="kwrd">bool</span> pressed = high == 1;<br /> <span class="kwrd">return</span> <span class="kwrd">new</span> KeyStateInfo(key, pressed, toggled);<br /> }<br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">int</span> High(<span class="kwrd">int</span> keyState)<br /> {<br /> <span class="kwrd">return</span> keyState > 0 ? keyState >> 0x10<br /> : (keyState >> 0x10) & 0x1;<br /> }<br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">int</span> Low(<span class="kwrd">int</span> keyState)<br /> {<br /> <span class="kwrd">return</span> keyState & 0xffff;<br /> }<br />}</pre><br /><br />Simple enough. To prove that this works now with more than one key, I wrote a simple windows app that moves a ball around the form based on the user's pressing of the arrow keys. You'll notice, that if you press two arrows at once, it will move the ball diagonally, proving that it accepts more than one key at a time. Here's the code:<br /><br />First, I created a simple Ball class:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Collections.Generic;<br /><span class="kwrd">using</span> System.Linq;<br /><span class="kwrd">using</span> System.Text;<br /><span class="kwrd">using</span> System.Drawing;<br /><br /><span class="kwrd">namespace</span> WindowsFormsApplication1<br />{<br /><span class="kwrd">public</span> <span class="kwrd">class</span> Ball<br />{<br /> <span class="kwrd">private</span> Brush brush;<br /><br /> <span class="kwrd">public</span> <span class="kwrd">float</span> X { get; set; }<br /> <span class="kwrd">public</span> <span class="kwrd">float</span> Y { get; set; }<br /> <span class="kwrd">public</span> <span class="kwrd">float</span> DX { get; set; }<br /> <span class="kwrd">public</span> <span class="kwrd">float</span> DY { get; set; }<br /> <span class="kwrd">public</span> Color Color { get; set; }<br /> <span class="kwrd">public</span> <span class="kwrd">float</span> Size { get; set; }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> Draw(Graphics g)<br /> {<br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.brush == <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">this</span>.brush = <span class="kwrd">new</span> SolidBrush(<span class="kwrd">this</span>.Color);<br /> }<br /> g.FillEllipse(<span class="kwrd">this</span>.brush, X, Y, Size, Size);<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> MoveRight()<br /> {<br /> <span class="kwrd">this</span>.X += DX;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> MoveLeft()<br /> {<br /> <span class="kwrd">this</span>.X -= <span class="kwrd">this</span>.DX;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> MoveUp()<br /> {<br /> <span class="kwrd">this</span>.Y -= <span class="kwrd">this</span>.DY;<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> MoveDown()<br /> {<br /> <span class="kwrd">this</span>.Y += <span class="kwrd">this</span>.DY;<br /> }<br />}<br /><br />}<br /></pre><br /><br />This class basically holds the coordinates of the ball, and the "velocity" (DX, and DY), or the speed at which the ball will move each time the key is pressed. It also holds the color and size.<br /><br />Then, here's the main Form code:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Drawing;<br /><span class="kwrd">using</span> System.Windows.Forms;<br /><br /><span class="kwrd">namespace</span> WindowsFormsApplication1<br />{<br /> <span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> Form1 : Form<br /> {<br /> <span class="kwrd">private</span> Ball ball;<br /> <span class="kwrd">private</span> Timer timer;<br /> <span class="kwrd">public</span> Form1()<br /> {<br /> InitializeComponent();<br /> <span class="kwrd">this</span>.ball = <span class="kwrd">new</span> Ball<br /> {<br /> X = 10f,<br /> Y = 10f,<br /> DX = 2f,<br /> DY = 2f,<br /> Color = Color.Red,<br /> Size = 10f<br /> };<br /> <span class="kwrd">this</span>.timer = <span class="kwrd">new</span> Timer();<br /> timer.Interval = 20;<br /> timer.Tick += <span class="kwrd">new</span> EventHandler(timer_Tick);<br /> timer.Start();<br /> }<br /><br /> <span class="kwrd">void</span> timer_Tick(<span class="kwrd">object</span> sender, EventArgs e)<br /> {<br /> var left = KeyboardInfo.GetKeyState(Keys.Left);<br /> var right = KeyboardInfo.GetKeyState(Keys.Right);<br /> var up = KeyboardInfo.GetKeyState(Keys.Up);<br /> var down = KeyboardInfo.GetKeyState(Keys.Down);<br /><br /> <span class="kwrd">if</span> (left.IsPressed)<br /> {<br /> ball.MoveLeft();<br /> <span class="kwrd">this</span>.Invalidate();<br /> }<br /><br /> <span class="kwrd">if</span> (right.IsPressed)<br /> {<br /> ball.MoveRight();<br /> <span class="kwrd">this</span>.Invalidate();<br /> }<br /><br /> <span class="kwrd">if</span> (up.IsPressed)<br /> {<br /> ball.MoveUp();<br /> <span class="kwrd">this</span>.Invalidate();<br /> }<br /><br /> <span class="kwrd">if</span> (down.IsPressed)<br /> {<br /> ball.MoveDown();<br /> <span class="kwrd">this</span>.Invalidate();<br /> }<br /><br /><br /> }<br /><br /><br /> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnPaint(PaintEventArgs e)<br /> {<br /> <span class="kwrd">base</span>.OnPaint(e);<br /> <span class="kwrd">if</span> (<span class="kwrd">this</span>.ball != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">this</span>.ball.Draw(e.Graphics);<br /> }<br /> }<br /> }<br /><br /><br />}<br /></pre><br />First, I create a red ball that's 10 pixels in size. Then, I create a Timer which will "tick" every 20 milliseconds. This is simple to simulate a game loop. It won't actually "Draw" every tick, it will only ever redraw if one of the arrow keys is pressed. The event handler for the Timer is where the meat of this lies:<br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">void</span> timer_Tick(<span class="kwrd">object</span> sender, EventArgs e)<br /> {<br /> var left = KeyboardInfo.GetKeyState(Keys.Left);<br /> var right = KeyboardInfo.GetKeyState(Keys.Right);<br /> var up = KeyboardInfo.GetKeyState(Keys.Up);<br /> var down = KeyboardInfo.GetKeyState(Keys.Down);<br /><br /> <span class="kwrd">if</span> (left.IsPressed)<br /> {<br /> ball.MoveLeft();<br /> <span class="kwrd">this</span>.Invalidate();<br /> }<br /><br /> <span class="kwrd">if</span> (right.IsPressed)<br /> {<br /> ball.MoveRight();<br /> <span class="kwrd">this</span>.Invalidate();<br /> }<br /><br /> <span class="kwrd">if</span> (up.IsPressed)<br /> {<br /> ball.MoveUp();<br /> <span class="kwrd">this</span>.Invalidate();<br /> }<br /><br /> <span class="kwrd">if</span> (down.IsPressed)<br /> {<br /> ball.MoveDown();<br /> <span class="kwrd">this</span>.Invalidate();<br /> }<br /> }</pre><br />First, we "poll" the keyboard for the arrows keys. We poll for all four of them, therefore if more than one is pressed, we'll be able to react to all of them. Then, if either key is held down, we move the ball in that direction and call Invalidate() to allow the form to repaint itself.<br /><br />One final thing I'd like to point out, is that with the standard KeyDown event in Windows Forms, you <span style="font-style: italic;">can </span>get "modifiers" (Shift, Ctrl, Alt etc.) as well as the key that was pressed. So if you're writing an app where you want to have some shortcut like say CTRL + A, you don't need to do this. This is only when you want to get info on more than one standard key................Which is why, you'll probably never need this in a real app outside of games (in which case, you're better off with XNA) but it's still something that's good to know.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com1tag:blogger.com,1999:blog-5611706923356552090.post-56561437382700541682009-03-31T08:56:00.006-04:002009-06-03T21:56:37.866-04:00.Net Memory Leaks. It IS possible!Let's face it; us .NET Developers have it pretty good these days. Ask any seasoned C++ programmer, and they'll undoubtedly have a few horror stories about an app they once worked on which had a memory leak somewhere someplace, and how hard it was to track down. When working in an unmanaged environment, this is part of the deal. Memory management is in your hands. When working in a managed environment, you just sit back and let the Garbage Collector do the dirty work. Therefore, it can be easy to simply assume that when coding in .NET you don't need to worry about memory leaks ever. Well, that's not entirely true as I'll demonstrate here.<br /><br />The premise is simple. If you have an object, we'll call it Foo, and this object holds a reference to an object that we'll call Bar. Now, Bar, has an event that can be raised at any time. Our Foo object registers for this event. Now, when our Foo object goes out of scope, and we lose a reference to it, if we DIDN'T unhook from the Bar event, Bar is still holding a reference to this object, and the Garbage Collector can't claim that memory back. We however, no longer have a reference to it directly, which now result in a nasty memory leak. Here's a simple demo app:<br /><br />First, let's create a class that raises an event. We'll call is EventRaiser:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">public</span> <span class="cb1">class</span> <span class="cb2">EventRaiser</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">string</span> stringValue;</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">string</span> StringValue</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">get</span> { <span class="cb1">return</span> <span class="cb1">this</span>.stringValue; }</pre><pre class="cl"> <span class="cb1">set</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">if</span> (<span class="cb1">this</span>.stringValue != <span class="cb1">value</span>)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.stringValue = <span class="cb1">value</span>;</pre><pre class="cl"> <span class="cb1">if</span> (<span class="cb1">this</span>.StringValueChanged != <span class="cb1">null</span>)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.StringValueChanged(<span class="cb1">this</span>, <span class="cb1">new</span> <span class="cb2">EventArgs</span>());</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">event</span> <span class="cb2">EventHandler</span> StringValueChanged;</pre><pre class="cl"> }</pre></div><br /><br />This class is nothing special, it just has a property called StringValue. Every time StringValue is changed, we raise our StringValueChanged event.<br /><br />Now, let's create a class that will have a reference to an EventRaiser object and will register for the StringValueChanged event:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: green; }</style><div class="cf"><pre class="cl"> <span class="cb1">public</span> <span class="cb1">class</span> <span class="cb2">MemoryLeak</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">byte</span>[] allocatedMemory;</pre><pre class="cl"> <span class="cb1">private</span> <span class="cb2">EventRaiser</span> raiser;</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">public</span> MemoryLeak(<span class="cb2">EventRaiser</span> raiser)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.raiser = raiser;</pre><pre class="cl"> <span class="cb3">//allocate some memory to mimic a real life object</span></pre><pre class="cl"> <span class="cb1">this</span>.allocatedMemory = <span class="cb1">new</span> <span class="cb1">byte</span>[10000]; </pre><pre class="cl"> raiser.StringValueChanged += <span class="cb1">new</span> <span class="cb2">EventHandler</span>(raiser_StringValueChanged);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> raiser_StringValueChanged(<span class="cb1">object</span> sender, <span class="cb2">EventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> </pre><pre class="cl"> }</pre><pre class="cl"> }</pre></div><br /><br />Here we create a MemoryLeak class. This class takes as a parameter in the constructor an object of type EventRaiser. It then allocates a large array of bytes, just to make the object a larger object in memory. It then hooks up to the EventRaiser's StringValueChanged event assigning it the raiser_StringValueChanged method. This is key! We're assigning a delegate to the EventRaiser class which therefore gives our EventRaiser object a reference to this MemoryLeak object. Remember, delegates are objects like any other and can hold on to references of other objects. Therefore, the EventRaiser.StringValueChanged event (delegate) holds on to a reference of our MemoryLeak object.<br /><br />Now, here's some code to demonstrate:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"> <span class="cb1">public</span> <span class="cb1">class</span> <span class="cb2">Program</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">static</span> <span class="cb2">EventRaiser</span> raiser;</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">static</span> <span class="cb1">void</span> Main(<span class="cb1">string</span>[] args)</pre><pre class="cl"> {</pre><pre class="cl"> raiser = <span class="cb1">new</span> <span class="cb2">EventRaiser</span>();</pre><pre class="cl"> <span class="cb1">for</span> (<span class="cb1">int</span> i = 0; i <= 1000; i++)</pre><pre class="cl"> {</pre><pre class="cl"> CreateLeak();</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb2">Console</span>.WriteLine(<span class="cb3">"Press any key to continue..."</span>);</pre><pre class="cl"> <span class="cb2">Console</span>.ReadKey(<span class="cb1">true</span>);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">static</span> <span class="cb1">void</span> CreateLeak()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb2">MemoryLeak</span> memoryLeak = <span class="cb1">new</span> <span class="cb2">MemoryLeak</span>(raiser);</pre><pre class="cl"> memoryLeak = <span class="cb1">null</span>;</pre><pre class="cl"> <span class="cb2">GC</span>.Collect();</pre><pre class="cl"> <span class="cb1">long</span> memory = <span class="cb2">GC</span>.GetTotalMemory(<span class="cb1">true</span>);</pre><pre class="cl"> <span class="cb2">Console</span>.WriteLine(<span class="cb3">"Memory being used: {0:0,0}"</span>, memory);</pre><pre class="cl"> }</pre><pre class="cl"> }</pre></div><br /><br />Simple console app that has a private field of type EventRaiser. In our main method, after we new up the EventRaiser, we call our CreateLeak method. All this method is doing is creating a new MemoryLeak object, pasing in the EventRaiser to the constructor. (At this point, the MemoryLeak will hook up to the StringValueChanged event of the EventRaiser.) Then, we assign the memoryLeak reference to null, which in a normal case would make the old MemoryLeak object subject to Garbage Collection. So, we call GC.Collect to force a collection, and then we output the amount of managed memory being used, using the <a href="http://msdn.microsoft.com/en-us/library/system.gc.gettotalmemory.aspx">GC.GetTotalMemory()</a> method. <br /><br />If you run this program, you'll notice that the amount of memory just keeps growing, and never goes down!! If you bump up the amount of bytes allocated in the MemoryLeak class, or bump up the number in the for loop in the main method, you'll get an OutOfMemoryException really quickly! <br /><br />The simplest way to avoid this kind of mess, is to take advantage of the <a href="http://msdn.microsoft.com/en-us/library/system.idisposable.aspx">IDiposable</a> interface. Let's add that to our MemoryLeak class and unhook from the event in the Dispose method:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: green; }</style><div class="cf"><pre class="cl"> <span class="cb1">public</span> <span class="cb1">class</span> <span class="cb2">MemoryLeak</span> : <span class="cb2">IDisposable</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">byte</span>[] allocatedMemory;</pre><pre class="cl"> <span class="cb1">private</span> <span class="cb2">EventRaiser</span> raiser;</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">public</span> MemoryLeak(<span class="cb2">EventRaiser</span> raiser)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.raiser = raiser;</pre><pre class="cl"> <span class="cb3">//allocate some memory to mimic a real life object</span></pre><pre class="cl"> <span class="cb1">this</span>.allocatedMemory = <span class="cb1">new</span> <span class="cb1">byte</span>[10000]; </pre><pre class="cl"> raiser.StringValueChanged += <span class="cb1">new</span> <span class="cb2">EventHandler</span>(raiser_StringValueChanged);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> raiser_StringValueChanged(<span class="cb1">object</span> sender, <span class="cb2">EventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> </pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">void</span> Dispose()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.raiser.StringValueChanged -= <span class="cb1">this</span>.raiser_StringValueChanged;</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> }</pre></div><br /><br />As you can see, in the Dispose method, we just unhook from the EventRaiser's StringValueChanged event. Now, we'll modify our main method to actually call the Dispose method:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"> <span class="cb1">private</span> <span class="cb1">static</span> <span class="cb1">void</span> CreateLeak()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb2">MemoryLeak</span> memoryLeak = <span class="cb1">new</span> <span class="cb2">MemoryLeak</span>(raiser);</pre><pre class="cl"> memoryLeak.Dispose();</pre><pre class="cl"> memoryLeak = <span class="cb1">null</span>;</pre><pre class="cl"> <span class="cb2">GC</span>.Collect();</pre><pre class="cl"> <span class="cb1">long</span> memory = <span class="cb2">GC</span>.GetTotalMemory(<span class="cb1">true</span>);</pre><pre class="cl"> <span class="cb2">Console</span>.WriteLine(<span class="cb3">"Memory being used: {0:0,0}"</span>, memory);</pre><pre class="cl"> }</pre></div><br /><br />Before we assign memoryLeak to null, we just call the Dispose method (or you can wrap the MemoryLeak assignment in a using statement). Now, run the program and what do you know?! The total memory being used stays the same throughout! Crisis averted.<br /><br />So, to anyone that thinks memory management in a managed world isn't important, think again. Yes, you don't activley have to play a role in the management of memory in your app, but you DO need to be conscious about it and understand what's going on.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com3tag:blogger.com,1999:blog-5611706923356552090.post-49259736443656420992009-03-29T13:24:00.007-04:002009-03-29T17:39:48.753-04:00WinForms Drag & Drop. A simple example to get you started.When using computers these days, we've all gotten accustomed to dragging and dropping things from one place to another. We do it all the time, and it gives your application that extra usability factor that the end user will appreciate. At work, I was working on an app that gave the user the ability to "Screen" on various columns of data. The user needed to have the ability to choose specifically which fields they want to screen on. So, we came up with the idea of having two treeviews. On the left hand side were all the available columns in the database and on the right was an empty treeview. The user would then be able to drag and drop fields from one to the other. So, here's the basic way of implementing Drag / Drop in your windows app.<br /><br />For simplicity in this example, I decided to go with a Listbox on the left and a Treeview on the right. The idea here will be simple. The user will be able to drag an item from the left, and move it to the treeview on the right. We will have to track where the user "drops" the item, so that we can place it under the proper parent node. Here's what the sample form looks like: <br><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhstIsQmjqO9WFUy8Fdw4mYjfMmCYIWplXAg3srHYAY5pKW5kd1E8T_n7EssbDUFwAT43Wmmcdxw1XmaxWAOVr_Qb6Rp1bqCf7XeIcqePtwHw4fc3zU0YxUhOQm8bbR_EqTWkETl-7ny04/s400/dragdropform.JPG"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand; width:100%; height:100%;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhstIsQmjqO9WFUy8Fdw4mYjfMmCYIWplXAg3srHYAY5pKW5kd1E8T_n7EssbDUFwAT43Wmmcdxw1XmaxWAOVr_Qb6Rp1bqCf7XeIcqePtwHw4fc3zU0YxUhOQm8bbR_EqTWkETl-7ny04/s400/dragdropform.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5318666998853313426" /></a><br /><br />When the form loads, we'll click on the Populate controls button. That will add the next 10 dates to the listbox on the left. It will also add two parents nodes to the treeview as well as two subnodes to each of the parent nodes. <br /><br />Here's the full code, I'll go through and explain it all as best I can:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"><span class="cb1">using</span> System;</pre><pre class="cl"><span class="cb1">using</span> System.Collections.Generic;</pre><pre class="cl"><span class="cb1">using</span> System.ComponentModel;</pre><pre class="cl"><span class="cb1">using</span> System.Data;</pre><pre class="cl"><span class="cb1">using</span> System.Drawing;</pre><pre class="cl"><span class="cb1">using</span> System.Linq;</pre><pre class="cl"><span class="cb1">using</span> System.Text;</pre><pre class="cl"><span class="cb1">using</span> System.Windows.Forms;</pre><pre class="cl"> </pre><pre class="cl"><span class="cb1">namespace</span> SetFocusDemo.DragDropSample</pre><pre class="cl">{</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">partial</span> <span class="cb1">class</span> <span class="cb2">DragDropSample</span> : <span class="cb2">Form</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">public</span> DragDropSample()</pre><pre class="cl"> {</pre><pre class="cl"> InitializeComponent();</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">this</span>.treeView1.AllowDrop = <span class="cb1">true</span>;</pre><pre class="cl"> <span class="cb1">this</span>.listBox1.AllowDrop = <span class="cb1">true</span>;</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">this</span>.listBox1.MouseDown += <span class="cb1">new</span> <span class="cb2">MouseEventHandler</span>(listBox1_MouseDown);</pre><pre class="cl"> <span class="cb1">this</span>.listBox1.DragOver += <span class="cb1">new</span> <span class="cb2">DragEventHandler</span>(listBox1_DragOver);</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">this</span>.treeView1.DragEnter += <span class="cb1">new</span> <span class="cb2">DragEventHandler</span>(treeView1_DragEnter);</pre><pre class="cl"> <span class="cb1">this</span>.treeView1.DragDrop += <span class="cb1">new</span> <span class="cb2">DragEventHandler</span>(treeView1_DragDrop);</pre><pre class="cl"> </pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> buttonPopulate_Click(<span class="cb1">object</span> sender, <span class="cb2">EventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.PopulateListBox();</pre><pre class="cl"> <span class="cb1">this</span>.PopulateTreeView();</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> PopulateListBox()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">for</span> (<span class="cb1">int</span> i = 0; i <= 10; i++)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.listBox1.Items.Add(<span class="cb2">DateTime</span>.Now.AddDays(i));</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> PopulateTreeView()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">for</span> (<span class="cb1">int</span> i = 1; i <= 2; i++)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb2">TreeNode</span> node = <span class="cb1">new</span> <span class="cb2">TreeNode</span>(<span class="cb3">"Node"</span> + i);</pre><pre class="cl"> <span class="cb1">for</span> (<span class="cb1">int</span> j = 1; j <= 2; j++)</pre><pre class="cl"> {</pre><pre class="cl"> node.Nodes.Add(<span class="cb3">"SubNode"</span> + j);</pre><pre class="cl"> }</pre><pre class="cl"> <span class="cb1">this</span>.treeView1.Nodes.Add(node);</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> listBox1_MouseDown(<span class="cb1">object</span> sender, <span class="cb2">MouseEventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.listBox1.DoDragDrop(<span class="cb1">this</span>.listBox1.SelectedItem, <span class="cb2">DragDropEffects</span>.Move);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> listBox1_DragOver(<span class="cb1">object</span> sender, <span class="cb2">DragEventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> e.Effect = <span class="cb2">DragDropEffects</span>.Move;</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> treeView1_DragEnter(<span class="cb1">object</span> sender, <span class="cb2">DragEventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> e.Effect = <span class="cb2">DragDropEffects</span>.Move;</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> treeView1_DragDrop(<span class="cb1">object</span> sender, <span class="cb2">DragEventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb2">TreeNode</span> nodeToDropIn = <span class="cb1">this</span>.treeView1.GetNodeAt(<span class="cb1">this</span>.treeView1.PointToClient(<span class="cb1">new</span> <span class="cb2">Point</span>(e.X, e.Y)));</pre><pre class="cl"> <span class="cb1">if</span> (nodeToDropIn == <span class="cb1">null</span>) { <span class="cb1">return</span>; }</pre><pre class="cl"> <span class="cb1">if</span> (nodeToDropIn.Level > 0)</pre><pre class="cl"> {</pre><pre class="cl"> nodeToDropIn = nodeToDropIn.Parent;</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">object</span> data = e.Data.GetData(<span class="cb1">typeof</span>(<span class="cb2">DateTime</span>));</pre><pre class="cl"> <span class="cb1">if</span> (data == <span class="cb1">null</span>) { <span class="cb1">return</span>; }</pre><pre class="cl"> nodeToDropIn.Nodes.Add(data.ToString());</pre><pre class="cl"> <span class="cb1">this</span>.listBox1.Items.Remove(data);</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl">}</pre></div><br /><br />Ok, let's start with the constructor. First thing you need to make sure, is that if you want a control to be a "Drop Target" you need to set the "AllowDrop" property to true. You'll also notice that we're setting the "AllowDrop" property of the listbox. Even though we won't actually be dropping anything in the listbox, the only way to get the correct icon while dragging out of the listbox, is to set it's AllowDrop to true as well.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">this</span>.listBox1.MouseDown += <span class="cb1">new</span> <span class="cb2">MouseEventHandler</span>(listBox1_MouseDown);</pre><pre class="cl"> <span class="cb1">this</span>.listBox1.DragOver += <span class="cb1">new</span> <span class="cb2">DragEventHandler</span>(listBox1_DragOver);</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">this</span>.treeView1.DragEnter += <span class="cb1">new</span> <span class="cb2">DragEventHandler</span>(treeView1_DragEnter);</pre><pre class="cl"> <span class="cb1">this</span>.treeView1.DragDrop += <span class="cb1">new</span> <span class="cb2">DragEventHandler</span>(treeView1_DragDrop);</pre></div><br /><br />Here, we hook up to all the events that we'll need to make this happen. I'll explain it when we get to the handlers.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> buttonPopulate_Click(<span class="cb1">object</span> sender, <span class="cb2">EventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.PopulateListBox();</pre><pre class="cl"> <span class="cb1">this</span>.PopulateTreeView();</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> PopulateListBox()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">for</span> (<span class="cb1">int</span> i = 0; i <= 10; i++)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.listBox1.Items.Add(<span class="cb2">DateTime</span>.Now.AddDays(i));</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> PopulateTreeView()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">for</span> (<span class="cb1">int</span> i = 1; i <= 2; i++)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb2">TreeNode</span> node = <span class="cb1">new</span> <span class="cb2">TreeNode</span>(<span class="cb3">"Node"</span> + i);</pre><pre class="cl"> <span class="cb1">for</span> (<span class="cb1">int</span> j = 1; j <= 2; j++)</pre><pre class="cl"> {</pre><pre class="cl"> node.Nodes.Add(<span class="cb3">"SubNode"</span> + j);</pre><pre class="cl"> }</pre><pre class="cl"> <span class="cb1">this</span>.treeView1.Nodes.Add(node);</pre><pre class="cl"> }</pre><pre class="cl"> }</pre></div><br /><br />This is just some demo code to set up are controls. In the PopulateListBox() method we just do a for loop from 0 to 10 and add the date for the next 10 days to the listbox. In the PopulateTreeView() method, we just put two parent nodes along with two child nodes in the treeview. Again, this is just for the purpose of this demo.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> listBox1_MouseDown(<span class="cb1">object</span> sender, <span class="cb2">MouseEventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.listBox1.DoDragDrop(<span class="cb1">this</span>.listBox1.SelectedItem, <span class="cb2">DragDropEffects</span>.Move);</pre><pre class="cl"> }</pre></div><br /><br />Here's where it starts getting interesting. The first event we deal with, is the "MouseDown" on the listbox. This kicks off the Drag / Drop; when the user actually clicks on an item. Here, we call "<a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.control.dodragdrop.aspx">DoDragDrop</a>" on the listbox. The arguments that the DoDragDrop method expect are "object data", and "<a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.dragdropeffects.aspx">DragDropEffects</a> allowedEffects". The data in the first argument, is the actual object that you want to move from one control to the other. In our case, we just grab the listbox selected item, which will be a DateTime. We then use the Move drag effect, which gives the nice visual mouse cursor we expect for a move.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> listBox1_DragOver(<span class="cb1">object</span> sender, <span class="cb2">DragEventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> e.Effect = <span class="cb2">DragDropEffects</span>.Move;</pre><pre class="cl"> }</pre></div><br /><br />The next event we handle is the listbox DragOver event. Since we called the DoDragDrop in the mousedown, when the user starts to "drag" the item out, the DragOver event is now raised in the listbox. We are only dealing with this event so that we can continue to show the "move" mouse cursor. <br /><br />Once the user leaves the Listbox, the DragLeave event is raised. In this case I'm not handling it because I have no need for it, but if you do need it, it does get raised.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> treeView1_DragEnter(<span class="cb1">object</span> sender, <span class="cb2">DragEventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> e.Effect = <span class="cb2">DragDropEffects</span>.Move;</pre><pre class="cl"> }</pre></div><br /><br />The next event we're listening for is the "DragEnter" on the Treeview. At this point, the user has clicked his mouse on one of the dates, dragged it out of the listbox, and now moved his mouse into the treeview. All we're doing here, is just setting the DragEffects to move so that we can continue to show the correct mouse cursor.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> treeView1_DragDrop(<span class="cb1">object</span> sender, <span class="cb2">DragEventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb2">TreeNode</span> nodeToDropIn = <span class="cb1">this</span>.treeView1.GetNodeAt(<span class="cb1">this</span>.treeView1.PointToClient(<span class="cb1">new</span> <span class="cb2">Point</span>(e.X, e.Y)));</pre><pre class="cl"> <span class="cb1">if</span> (nodeToDropIn == <span class="cb1">null</span>) { <span class="cb1">return</span>; }</pre><pre class="cl"> <span class="cb1">if</span> (nodeToDropIn.Level > 0)</pre><pre class="cl"> {</pre><pre class="cl"> nodeToDropIn = nodeToDropIn.Parent;</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">object</span> data = e.Data.GetData(<span class="cb1">typeof</span>(<span class="cb2">DateTime</span>));</pre><pre class="cl"> <span class="cb1">if</span> (data == <span class="cb1">null</span>) { <span class="cb1">return</span>; }</pre><pre class="cl"> nodeToDropIn.Nodes.Add(data.ToString());</pre><pre class="cl"> <span class="cb1">this</span>.listBox1.Items.Remove(data);</pre><pre class="cl"> }</pre></div><br /><br />Finally, we actually deal with the "main event" (pun intended). This is where the user finally lets go of the mouse and "Drops" the item into the TreeView. First we need to determine where the user let go of his mouse. There's a very helpful method on the TreeView called "<a href="http://msdn.microsoft.com/en-us/library/1yxbz43s.aspx">GetNodeAt(Point pt)</a>" which takes a Point as a parameter, and gives you back the TreeNode at that location. The Point that's passed to us through the DragEventArgs is in screen coordinates. Therefore, we first need to call "<a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.control.pointtoclient.aspx">PointToClient</a>" to get us the coordinates relative to the TreeView. Once we have that, we can get the exact node where the user let go of the mouse.<br /><br />Now, we just need to determine if the node where the user dropped the item is a parent node or a child node. This is the business rule I decided to set up for this example; that the user can only drag a date into the treeview as a subnode. We will not allow them to add parent nodes. Therefore, we first need to determine if the node is a parent or a sub. Once we have the parent node, we will add the dropped item as a subnode.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">object</span> data = e.Data.GetData(<span class="cb1">typeof</span>(<span class="cb2">DateTime</span>));</pre><pre class="cl"> <span class="cb1">if</span> (data == <span class="cb1">null</span>) { <span class="cb1">return</span>; }</pre></div><br /><br />Here we retrieve the item that was brought over from the listbox through the eventargs. We call the GetData method to actually retrieve the item which in our case is a DateTime object. <br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }</style><div class="cf"><pre class="cl"> nodeToDropIn.Nodes.Add(data.ToString());</pre><pre class="cl"> <span class="cb1">this</span>.listBox1.Items.Remove(data);</pre></div><br /><br />Once that's done, we just add it as a node, and remove the item from the listbox. Run the sample and try it yourself. Click the Populate Button and then drag items from the listbox to the treeview. Cool stuff no?<br /><br />I admit, it's a bit of a pain to get this all to work, but the end result is worth it. Users are accustomed to drag and drop and will appreciate the extra touch in your app.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com2tag:blogger.com,1999:blog-5611706923356552090.post-66558412823358829052009-03-25T08:59:00.007-04:002009-03-25T12:41:13.184-04:00Cool IEnumberable extension method. Useful in ASP.NET MVCSo recently at work we started revamping our site and we've decided to use <a href="http://www.asp.net/mvc/">ASP.NET MVC</a>. I'm not going to cover ASP.NET MVC in this blog post (hopefully in the future) but in short, it's Microsoft's new Web Framework that doesn't use WebForms. No more postbacks for every little thing! Woohoo! However, without WebForms, that means no more ASP.NET controls. Therefore, it was useful for us in a few places to be able to generate an HTML table from a collection of various different objects. So, I ended up writing a really cool extension method which I think can be beneficial since it covers generics, and reflection (two topics that wasn't explored thoroughly enough in SetFocus IMO).<br /><br />So, first I'll show the code, then I'll do my best to explain:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background-color: #CCFFFF; overflow:auto; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"><span class="cb1"> public</span> <span class="cb1">static</span> <span class="cb1">string</span> ToHtmlTable<T>(<span class="cb1">this</span> <span class="cb2">IEnumerable</span><T> list,<span class="cb1">string</span> tableSyle, <span class="cb1">string</span> headerStyle, <span class="cb1">string</span> rowStyle, <span class="cb1">string</span> alternateRowStyle)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">var</span> result = <span class="cb1">new</span> <span class="cb2">StringBuilder</span>();</pre><pre class="cl"> <span class="cb1">if</span> (<span class="cb2">String</span>.IsNullOrEmpty(tableSyle))</pre><pre class="cl"> {</pre><pre class="cl"> result.Append(<span class="cb3">"<table id=\""</span> + <span class="cb1">typeof</span>(T).Name + <span class="cb3">"Table\">"</span>);</pre><pre class="cl"> }</pre><pre class="cl"> <span class="cb1">else</span></pre><pre class="cl"> {</pre><pre class="cl"> result.Append(<span class="cb3">"<table id=\""</span> + <span class="cb1">typeof</span>(T).Name + <span class="cb3">"Table\" class=\""</span> + tableSyle + <span class="cb3">"\">"</span>);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">var</span> propertyArray = <span class="cb1">typeof</span>(T).GetProperties();</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">foreach</span> (<span class="cb1">var</span> prop <span class="cb1">in</span> propertyArray)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">if</span> (<span class="cb2">String</span>.IsNullOrEmpty(headerStyle))</pre><pre class="cl"> {</pre><pre class="cl"> result.AppendFormat(<span class="cb3">"<th>{0}</th>"</span>, prop.Name);</pre><pre class="cl"> }</pre><pre class="cl"> <span class="cb1">else</span></pre><pre class="cl"> {</pre><pre class="cl"> result.AppendFormat(<span class="cb3">"<th class=\"{0}\">{1}</th>"</span>,headerStyle, prop.Name);</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">for</span> (<span class="cb1">int</span> i = 0; i < list.Count(); i++)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">if</span> (!<span class="cb2">String</span>.IsNullOrEmpty(rowStyle) && !<span class="cb2">String</span>.IsNullOrEmpty(alternateRowStyle))</pre><pre class="cl"> {</pre><pre class="cl"> result.AppendFormat(<span class="cb3">"<tr class=\"{0}\">"</span>, i%2==0 ? rowStyle : alternateRowStyle);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">else</span></pre><pre class="cl"> {</pre><pre class="cl"> result.AppendFormat(<span class="cb3">"<tr>"</span>);</pre><pre class="cl"> }</pre><pre class="cl"> <span class="cb1">foreach</span> (<span class="cb1">var</span> prop <span class="cb1">in</span> propertyArray)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">object</span> value = prop.GetValue(list.ElementAt(i), <span class="cb1">null</span>);</pre><pre class="cl"> result.AppendFormat(<span class="cb3">"<td>{0}</td>"</span>, value ?? <span class="cb2">String</span>.Empty);</pre><pre class="cl"> }</pre><pre class="cl"> result.AppendLine(<span class="cb3">"</tr>"</span>);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> result.Append(<span class="cb3">"</table>"</span>);</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">return</span> result.ToString();</pre><pre class="cl"> }</pre></div><br /><br />Ok, let's start with the parameters:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">public</span> <span class="cb1">static</span> <span class="cb1">string</span> ToHtmlTable<T>(<span class="cb1">this</span> <span class="cb2">IEnumerable</span><T> list,<span class="cb1">string</span> tableSyle, <span class="cb1">string</span> headerStyle, <span class="cb1">string</span> rowStyle, <span class="cb1">string</span> alternateRowStyle)</pre></div><br /><br />This will allow us to pass in the CSS class of each piece in the HTML table. The way it's coded is that you can pass in null or empty strings and it'll ignore it. Otherwise, it'll enter that as the class name. IE:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }</style><div class="cf"><pre class="cl"><span class="cb1"><table class="tableClass"></span></pre></div><br /><br />Also notice that the method is generic, so any collection of any kind will work with this method.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"> <span class="cb1">var</span> result = <span class="cb1">new</span> <span class="cb2">StringBuilder</span>();</pre><pre class="cl"> <span class="cb1">if</span> (<span class="cb2">String</span>.IsNullOrEmpty(tableSyle))</pre><pre class="cl"> {</pre><pre class="cl"> result.Append(<span class="cb3">"<table id=\""</span> + <span class="cb1">typeof</span>(T).Name + <span class="cb3">"Table\">"</span>);</pre><pre class="cl"> }</pre><pre class="cl"> <span class="cb1">else</span></pre><pre class="cl"> {</pre><pre class="cl"> result.Append(<span class="cb3">"<table id=\""</span> + <span class="cb1">typeof</span>(T).Name + <span class="cb3">"Table\" class=\""</span> + tableSyle + <span class="cb3">"\">"</span>);</pre><pre class="cl"> }</pre></div><br /><br />Here we start building up the HTML table. If a CSS class was supplied for the table, then we put that in the table tag, otherwise, we don't put any class name. I gave it an ID based on the name of the type that T represents. This may be useful if you want to apply further CSS, so it's good practice to give every element an ID, but in our example we won't actually make use of it. I just left it there for completeness.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }</style><div class="cf"><pre class="cl"> <span class="cb1">var</span> propertyArray = <span class="cb1">typeof</span>(T).GetProperties();</pre></div><br /><br />Here's where we reflect over T to get an array of PropertyInfo objects. GetProperties returns a PropertyInfo[] array.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"> <span class="cb1">foreach</span> (<span class="cb1">var</span> prop <span class="cb1">in</span> propertyArray)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">if</span> (<span class="cb2">String</span>.IsNullOrEmpty(headerStyle))</pre><pre class="cl"> {</pre><pre class="cl"> result.AppendFormat(<span class="cb3">"<th>{0}</th>"</span>, prop.Name);</pre><pre class="cl"> }</pre><pre class="cl"> <span class="cb1">else</span></pre><pre class="cl"> {</pre><pre class="cl"> result.AppendFormat(<span class="cb3">"<th class=\"{0}\">{1}</th>"</span>,headerStyle, prop.Name);</pre><pre class="cl"> }</pre></div><br /><br />Next, we want to set up the table headers. The headers of the HTML table will be the actual property name. So say you were passing in a List to this method, and your Car class had properties such as "Year", "Make" etc, then that's what would actually appear as the column headers. That's what the PropertyInfo.Name property represents.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"> <span class="cb1">for</span> (<span class="cb1">int</span> i = 0; i < list.Count(); i++)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">if</span> (!<span class="cb2">String</span>.IsNullOrEmpty(rowStyle) && !<span class="cb2">String</span>.IsNullOrEmpty(alternateRowStyle))</pre><pre class="cl"> {</pre><pre class="cl"> result.AppendFormat(<span class="cb3">"<tr class=\"{0}\">"</span>, i%2==0 ? rowStyle : alternateRowStyle);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">else</span></pre><pre class="cl"> {</pre><pre class="cl"> result.AppendFormat(<span class="cb3">"<tr>"</span>);</pre><pre class="cl"> }</pre></div><br /><br />Here we start enumerating the actual IEnumerable that was passed in. For every element in the collection, we want to add a row to our table. Thefore, we first open the tag. However, if the styles for rows are set (both rowStyle and alternateRowStyle) then we need to apply the appropriate class to the row. We can simply check if i is currently an even number (i % 2 == 0). If it is, then we're on a regular row, if it's odd, then we're on an alternate row. If no style is specified, just do a regular tag.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #a31515; }.cb3 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">foreach</span> (<span class="cb1">var</span> prop <span class="cb1">in</span> propertyArray)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">object</span> value = prop.GetValue(list.ElementAt(i), <span class="cb1">null</span>);</pre><pre class="cl"> result.AppendFormat(<span class="cb2">"<td>{0}</td>"</span>, value ?? <span class="cb3">String</span>.Empty);</pre><pre class="cl"> }</pre><pre class="cl"> result.AppendLine(<span class="cb2">"</tr>"</span>);</pre><pre class="cl"> }</pre></div><br /><br />Now, we go back to using our PropertyInfo array. For each item in our collection, we want to enumerate over all of it's properties, and get the value for that property. Therefore, first we call the GetValue method on the current PropertyInfo. The first parameter to GetValue, is the object of whose value you want to get. The second one, is if parameters are neccessary to access that property like an indexer. We won't be dealing with that here so we just pass null.<br /><br />Then, if value isn't null, we append that to the table, else we append a String.Empty. You'll notice the syntax is value ?? String.Empty. That's actually called the "<a href="http://msdn.microsoft.com/en-us/library/ms173224.aspx">null coalescing operator</a>" It's basically a shorthand way of saying "If value isn't null, use value, else use String.Empty".<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: #a31515; }.cb2 { color: blue; }</style><div class="cf"><pre class="cl"> result.Append(<span class="cb1">"</table>"</span>);</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb2">return</span> result.ToString();</pre><pre class="cl"> }</pre></div><br /><br />Finally, we just close up the tag and then the tag. Then, we return the result. Now, let's actually test this!<br /><br />Create a winforms project and add a button to the form, and a WebBrowser control. Then, create a simple Person class like this:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">public</span> <span class="cb1">class</span> <span class="cb2">Person</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">string</span> FirstName { <span class="cb1">get</span>; <span class="cb1">set</span>; }</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">string</span> LastName { <span class="cb1">get</span>; <span class="cb1">set</span>; }</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">int</span> Age { <span class="cb1">get</span>; <span class="cb1">set</span>; }</pre><pre class="cl"> }</pre></div><br /><br />No big deal, simple class with three properties. Then, in the button click, create a new List and add a few Person objects to that list:<br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> button1_Click(<span class="cb1">object</span> sender, <span class="cb2">EventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">var</span> personList = <span class="cb1">new</span> <span class="cb2">List</span><<span class="cb2">Person</span>>();</pre><pre class="cl"> personList.Add(<span class="cb1">new</span> <span class="cb2">Person</span></pre><pre class="cl"> {</pre><pre class="cl"> FirstName = <span class="cb3">"Alex"</span>,</pre><pre class="cl"> LastName = <span class="cb3">"Friedman"</span>,</pre><pre class="cl"> Age = 27</pre><pre class="cl"> });</pre><pre class="cl"> </pre><pre class="cl"> personList.Add(<span class="cb1">new</span> <span class="cb2">Person</span></pre><pre class="cl"> {</pre><pre class="cl"> FirstName = <span class="cb3">"Jack"</span>,</pre><pre class="cl"> LastName = <span class="cb3">"Bauer"</span>,</pre><pre class="cl"> Age = 45</pre><pre class="cl"> });</pre><pre class="cl"> </pre><pre class="cl"> personList.Add(<span class="cb1">new</span> <span class="cb2">Person</span></pre><pre class="cl"> {</pre><pre class="cl"> FirstName = <span class="cb3">"Cloe"</span>,</pre><pre class="cl"> LastName = <span class="cb3">"O'Brien"</span>,</pre><pre class="cl"> Age = 35</pre><pre class="cl"> });</pre><pre class="cl"> </pre><pre class="cl"> personList.Add(<span class="cb1">new</span> <span class="cb2">Person</span></pre><pre class="cl"> {</pre><pre class="cl"> FirstName = <span class="cb3">"John"</span>,</pre><pre class="cl"> LastName = <span class="cb3">"Doe"</span>,</pre><pre class="cl"> Age = 30</pre><pre class="cl"> });</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">string</span> html = <span class="cb3">@"<style type = ""text/css""> .tableStyle{border: solid 5 green;} </span></pre><pre class="cl"><span class="cb3">th.header{ background-color:#FF3300} tr.rowStyle { background-color:#33FFFF; </span></pre><pre class="cl"><span class="cb3">border: solid 1 black; } tr.alternate { background-color:#99FF66; </span></pre><pre class="cl"><span class="cb3">border: solid 1 black;}</style>"</span>;</pre><pre class="cl"> html += personList.ToHtmlTable(<span class="cb3">"tableStyle"</span>, <span class="cb3">"header"</span>, <span class="cb3">"rowStyle"</span>, <span class="cb3">"alternate"</span>);</pre><pre class="cl"> <span class="cb1">this</span>.webBrowser1.DocumentText = html;</pre><pre class="cl"> }</pre></div><br /><br />Then, I created an html string with all the different CSS styles to simulate a real life scenario where you'll actually have those classes in your CSS file. Finally, call the ToHtmlTable method, and set the webBrowser's DocumentText to the HTML. This is the result:<br /><br /><style type = "text/css"> .tableStyle{border: solid 5 green;} th.header{ background-color:#FF3300} tr.rowStyle { background-color:#33FFFF; border: solid 1 black; } tr.alternate { background-color:#99FF66; border: solid 1 black;}</style><table id="PersonTable" class="tableStyle"><th class="header">FirstName</th><th class="header">LastName</th><th class="header">Age</th><tr class="rowStyle"><td>Alex</td><td>Friedman</td><td>27</td></tr><br /><tr class="alternate"><td>Jack</td><td>Bauer</td><td>45</td></tr><br /><tr class="rowStyle"><td>Cloe</td><td>O'Brien</td><td>35</td></tr><br /><tr class="alternate"><td>John</td><td>Doe</td><td>30</td></tr><br /></table><br /><br />Yuck, those colors are nasty! But you get the idea. The nice thing is, since it's generic, and on IEnumerable, any collection of objects that you have can now be turned into an HTML table by calling this one method. Gotta love generics and reflection.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com4tag:blogger.com,1999:blog-5611706923356552090.post-4789442837977754692009-03-23T10:49:00.002-04:002009-03-23T12:02:17.544-04:00Calling unmanaged API's from within your C# app using P/Invoke.While the .NET Framework is HUGE and you generally can find anything you need to do, there are often times when you need to call unmanaged API's from within your code. For example, there are many great functions in the Windows API that simply have no wrapper or equivalent in the Framework. Or, say if you have a fully working and tested library that was written in unmanaged code (like C/C++) why rewrite the entire thing? Why not call into the existing library? That's where the idea of P/Invoke (Platform Invoke) comes into play. I'll demonstrate with a few examples:
<br />
<br />The first one I'll show is actually a very simple one, but actually extremely useful. Many times when working in WinForms apps, I find myself needing a Console for debugging. It's much easier to do Console.Writeline's when there's an actual Console, rather than having to look in the tiny Output window in VS. Here's how you can do it. First, create a simple WindowsForm application and add a button on to the form. Then add these few lines of code:
<br />
<br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: #2b91af; }.cb2 { color: #a31515; }.cb3 { color: blue; }</style><div class="cf"><pre class="cl"> [<span class="cb1">DllImport</span>(<span class="cb2">"kernel32.dll"</span>)]</pre><pre class="cl"> <span class="cb3">public</span> <span class="cb3">static</span> <span class="cb3">extern</span> <span class="cb3">bool</span> AllocConsole();</pre><pre class="cl"> </pre><pre class="cl"> [<span class="cb1">DllImport</span>(<span class="cb2">"kernel32.dll"</span>)]</pre><pre class="cl"> <span class="cb3">public</span> <span class="cb3">static</span> <span class="cb3">extern</span> <span class="cb3">bool</span> FreeConsole();</pre></div>
<br />You'll have to add this using statement at the top of your class:
<br />
<br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }</style><div class="cf"><pre class="cl"><span class="cb1">using</span> System.Runtime.InteropServices;</pre></div>
<br />The "DllImport" attribute tells the CLR that this function lives outside the managed world. You then specify the dll where this function lives. You then just need to specify the function name and provide the signature. Here's what the actual <a href="http://msdn.microsoft.com/en-us/library/ms681944%28VS.85%29.aspx">AllocConole</a> method looks like in the windows API:
<br />
<br /><div class="" id="ctl00_rs1_mainContentContainer_ctl01_C++"><div class="CodeSnippetTitleBar"><div class="CodeDisplayLanguage">C++</div></div><div dir="ltr"><pre class="libCScode" style="white-space: pre-wrap;" id="ctl00_rs1_mainContentContainer_ctl01C++" space="preserve">BOOL WINAPI AllocConsole(void);
<br /></pre></div></div>So as long as you use the same name, it can map the function. You also need to make the method static, and mark it as extern.
<br />
<br />Now, you can just call it like any other method. Add this code to the button1 click:
<br />
<br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"><span class="cb1"> private</span> <span class="cb1">void</span> button1_Click(<span class="cb1">object</span> sender, <span class="cb2">EventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> AllocConsole();</pre><pre class="cl"> <span class="cb2">Console</span>.WriteLine(<span class="cb3">"Writing this to a console from a Windows App."</span>);</pre><pre class="cl"> }</pre></div>
<br />Run the program and click the button. You'll see a console window show up, and our message will be written to the console. The console will stick around though, as we never told it to go away. Add another button to your form and put this code in there:
<br />
<br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"><span class="cb1"> private</span> <span class="cb1">void</span> button2_Click(<span class="cb1">object</span> sender, <span class="cb2">EventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb2">Console</span>.WriteLine(<span class="cb3">"Press any key to close the console."</span>);</pre><pre class="cl"> <span class="cb2">Console</span>.ReadKey(<span class="cb1">true</span>);</pre><pre class="cl"> FreeConsole();</pre><pre class="cl"> }</pre></div>
<br />Run it again, click the first button, then click the second. After you hit a key on your keyboard, the console will disappear. I'm only demonstrating this to give you an intro to P/Invoke, but you'll see, this AllocConsole stuff is actually real useful for debugging Windows Apps.
<br />
<br />Now let's move on to another one that's a bit more complicated. In the C/C++ world, very often you'll find that functions take Structs instead of a list of parameters. I'm not a C++ guy myself, so don't ask me why, but that's the way it is. Therefore, in order to P/Invoke such a method, you need to recreate that struct in your C# app. Example:
<br />
<br />If you've ever used any chatting program, you'll notice that when the chat window is minimized, if you receive an instant message, the minimized window in your taskbar starts to blink. There doesn't exist a way to do this in .NET <meta equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 10"><meta name="Originator" content="Microsoft Word 10"><link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CBumi%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"><!--[if gte mso 9]><xml> <w:worddocument> <w:view>Normal</w:View> <w:zoom>0</w:Zoom> <w:compatibility> <w:breakwrappedtables/> <w:snaptogridincell/> <w:wraptextwithpunct/> <w:useasianbreakrules/> </w:Compatibility> <w:browserlevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><style> <!-- /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} @page Section1 {size:8.5in 11.0in; margin:1.0in 1.25in 1.0in 1.25in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.Section1 {page:Section1;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman";} </style> <![endif]--><span style="font-size: 12pt; font-family: "Times New Roman";">unfortunately</span>, therefore we will have to P/Invoke it. The Windows Function for this is called: <a href="http://msdn.microsoft.com/en-us/library/ms679347%28VS.85%29.aspx">FlashWindowEx</a>. Now, if you click on that link, you'll notice that the signature for that method is:
<br />
<br /><pre class="libCScode" style="white-space: pre-wrap;" id="ctl00_rs1_mainContentContainer_ctl01C++" space="preserve">BOOL WINAPI FlashWindowEx(
<br /> __in PFLASHWINFO <em>pfwi</em>
<br />);
<br /></pre>What on earth is _in and what's PFLASHWINFO??? Well, here's where it gets interesting. "_in" means that the parameter being passed in is actually a <span style="font-style: italic;">pointer </span>to the parameter. Secondly, the PFLASHWINFO is a struct. On that page, you'll notice that in the documentation the PFLASHWINFO is a link that takes you to <a href="http://msdn.microsoft.com/en-us/library/ms679348%28VS.85%29.aspx">this</a> page, which shows this:
<br />
<br /><pre class="libCScode" style="white-space: pre-wrap;" id="ctl00_rs1_mainContentContainer_ctl01C++" space="preserve">typedef struct {
<br /> UINT cbSize;
<br /> HWND hwnd;
<br /> DWORD dwFlags;
<br /> UINT uCount;
<br /> DWORD dwTimeout;
<br />} FLASHWINFO, *PFLASHWINFO;</pre>Ok, we're getting somewhere, but looking at that list, (not being a C++ programmer) I can figure out UINT because we have uint in C#, but what's HWND? What's DWORD? How can I create a struct in C# if I don't know those datatypes? That's where you'll need <a href="http://www.codeproject.com/KB/dotnet/Win32APICPlusPlustoDotNET.aspx?print=true">this</a> page. It's a great article on Code Project which has a huge list about halfway down that maps all the C++ data types to C#.
<br />
<br />So, looking at that page, we can map everything we need. DWORD is a uint, and HWND is an IntPtr. (IntPtr is a .NET struct that basically represents a pointer. It's used very often when P/Invoking methods. For more info, see <a href="http://msdn.microsoft.com/en-us/library/system.intptr.aspx">this article.</a>)
<br />
<br />So, let's create our struct:
<br />
<br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"><span class="cb1"> public</span> <span class="cb1">struct</span> <span class="cb2">FLASHWINFO</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">uint</span> cbSize;</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb2">IntPtr</span> hwnd;</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">uint</span> dwFlags;</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">uint</span> uCount;</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">uint</span> dwTimeout;</pre><pre class="cl"> }
<br /></pre></div>
<br />Ok, we're getting somewhere. We have the struct, but remember, a POINTER to this struct was used to call the Windows API. Well, structs are valuetypes, so by passing a struct using the "ref" keyword, you're essentially doing the same thing. Therefore, we can now add this line to the top of our form:
<br />
<br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: #2b91af; }.cb2 { color: #a31515; }.cb3 { color: blue; }</style><div class="cf"><pre class="cl"> [<span class="cb1">DllImport</span>(<span class="cb2">"User32.dll"</span>)]</pre><pre class="cl"> <span class="cb3">public</span> <span class="cb3">static</span> <span class="cb3">extern</span> <span class="cb3">bool</span> FlashWindowEx(<span class="cb3">ref</span> <span class="cb1">FLASHWINFO</span> pfwi);</pre></div>
<br />You'll notice that this time I'm calling User32.dll. How did I know that? Well, if you refer back to the <a href="http://msdn.microsoft.com/en-us/library/ms679347%28VS.85%29.aspx">original MSDN page</a> that had the FlashWindowEx function declaration, you'll notice at the bottom of the page it says: DLL: User32.dll.
<br />
<br />OK, so we set up the method and the P/Invoke, but how do we actually use this now? Let's add a third button to our Form. The basic premise will be when this button will be clicked, the window will minimize. Then, after about a second, i'll start blinking.
<br />
<br />So, let's add a Flash method to our form:
<br />
<br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"><span class="cb1"> </span>
<br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: green; }</style><div class="cf"><pre class="cl"><span class="cb1"> private</span> <span class="cb1">void</span> Flash()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb2">FLASHWINFO</span> pwfi = <span class="cb1">new</span> <span class="cb2">FLASHWINFO</span>();</pre><pre class="cl"> <span class="cb3">//assign the windows handle of our Form</span></pre><pre class="cl"> pwfi.hwnd = <span class="cb1">this</span>.Handle;</pre><pre class="cl"> <span class="cb3">//size of the struct. Needed for the unmanaged world to allocated correct number of bytes</span></pre><pre class="cl"> pwfi.cbSize = <span class="cb2">Convert</span>.ToUInt32(<span class="cb2">Marshal</span>.SizeOf(<span class="cb1">typeof</span>(<span class="cb2">FLASHWINFO</span>)));</pre><pre class="cl"> <span class="cb3">//number of times to blink. We want max possible</span></pre><pre class="cl"> pwfi.uCount = <span class="cb1">uint</span>.MaxValue;</pre><pre class="cl"> <span class="cb3">//the flash status. 2 = taskbar only</span></pre><pre class="cl"> pwfi.dwFlags = 2;</pre><pre class="cl"> </pre><pre class="cl"> FlashWindowEx(<span class="cb1">ref</span> pwfi);</pre><pre class="cl"> }</pre></div>
<br /></pre></div>
<br />First, <a href="http://msdn.microsoft.com/en-us/library/ms679348%28VS.85%29.aspx">look at thist page again.</a> That explains what all the values in the struct represent. This way, we can know which values to assign to all the properties in our struct.
<br />
<br /><pre class="cl"><pre class="cl"><span class="cb2"> FLASHWINFO</span> pwfi = <span class="cb1">new</span> <span class="cb2">FLASHWINFO</span>();</pre><pre class="cl"> <span class="cb3">//assign the windows handle of our Form</span></pre><pre class="cl"> pwfi.hwnd = <span class="cb1">this</span>.Handle;</pre></pre>
<br />
<br />So first we create an instance of the struct. Then, in Windows Programming, every Window has something that's called a "Handle". <a href="http://wiki.answers.com/Q/What_is_a_handle_in_Windows_Programming">Here's a good explanation</a>:
<br />
<br /><blockquote>A handle is a reference for the operating system. It does not have the semantics of a programming reference but what it does do is allow the system resources to know what you are referring to when it is passed in an API call. </blockquote>So, in .NET every Form has a Handle property that returns an IntPtr.
<br />
<br /><pre class="cl"><pre class="cl"><span class="cb3">//size of the struct. Needed for the unmanaged world to allocated correct number of bytes</span></pre><pre class="cl"> pwfi.cbSize = <span class="cb2">Convert</span>.ToUInt32(<span class="cb2">Marshal</span>.SizeOf(<span class="cb1">typeof</span>(<span class="cb2">FLASHWINFO</span>)));</pre></pre>
<br />
<br />The next line is needed for the unmanaged world to know how many bytes to allocated for our struct. The Marshal class has alot of helper methods to interact with the unmanaged world.
<br />
<br /><pre class="cl"><pre class="cl"><span class="cb3">//number of times to blink. We want max possible</span></pre><pre class="cl"> pwfi.uCount = <span class="cb1">uint</span>.MaxValue;</pre></pre>
<br />
<br />The next piece is the uCount. This represents that number of times the icon should blink. We'll just assign it to the max possible. Our intention is to have it blink until the user brings the window back into view.
<br />
<br /><pre class="cl"><pre class="cl"><span class="cb3">//the flash status. 2 = taskbar only</span></pre><pre class="cl"> pwfi.dwFlags = 2;</pre></pre>
<br />
<br />The next property is the dwFlags which according to MSDN is the flash status. If you look at that page you'll see that these are the options:
<br />
<br /><table><tbody><tr><th>Value</th><th>Meaning</th></tr> <tr><td> <dl><dt>FLASHW_ALL</dt><dt>0x00000003</dt></dl> </td><td><p>Flash both the window caption and taskbar button. This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags.</p> </td></tr> <tr><td> <dl><dt>FLASHW_CAPTION</dt><dt>0x00000001</dt></dl> </td><td><p>Flash the window caption.</p> </td></tr> <tr><td> <dl><dt>FLASHW_STOP</dt><dt>0</dt></dl> </td><td><p>Stop flashing. The system restores the window to its original state.</p> </td></tr> <tr><td> <dl><dt>FLASHW_TIMER</dt><dt>0x00000004</dt></dl> </td><td><p>Flash continuously, until the FLASHW_STOP flag is set.</p> </td></tr> <tr><td> <dl><dt>FLASHW_TIMERNOFG</dt><dt>0x0000000C</dt></dl> </td><td><p>Flash continuously until the window comes to the foreground.</p> </td></tr> <tr><td> <dl><dt>FLASHW_TRAY</dt><dt>0x00000002</dt></dl> </td><td><p>Flash the taskbar button.</p></td></tr></tbody></table>In our case we want just the icon to flash just in the tray. Therefore we set the value to 2.
<br />
<br /><pre class="cl"><pre class="cl">FlashWindowEx(<span class="cb1">ref</span> pwfi);</pre></pre>
<br />Finally, we just call the method.
<br />
<br />At this point, the form will continue to blink. Therefore, we need a way to stop it. Let's create a StopFlashing method:
<br />
<br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> StopFlashing()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb2">FLASHWINFO</span> pwfi = <span class="cb1">new</span> <span class="cb2">FLASHWINFO</span>();</pre><pre class="cl"> pwfi.hwnd = <span class="cb1">this</span>.Handle;</pre><pre class="cl"> pwfi.cbSize = <span class="cb2">Convert</span>.ToUInt32(<span class="cb2">Marshal</span>.SizeOf(<span class="cb1">typeof</span>(<span class="cb2">FLASHWINFO</span>)));</pre><pre class="cl"> pwfi.uCount = <span class="cb1">uint</span>.MaxValue;</pre><pre class="cl"> pwfi.dwFlags = 0;</pre><pre class="cl"> </pre><pre class="cl"> FlashWindowEx(<span class="cb1">ref</span> pwfi);</pre><pre class="cl"> }</pre></div>
<br />Really the same as before except the dwFlags is set to 0 which means stop. So, now here's the entired Form code:
<br />
<br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }.cb4 { color: green; }</style><div class="cf"><pre class="cl"><span class="cb1">using</span> System;</pre><pre class="cl"><span class="cb1">using</span> System.Collections.Generic;</pre><pre class="cl"><span class="cb1">using</span> System.ComponentModel;</pre><pre class="cl"><span class="cb1">using</span> System.Data;</pre><pre class="cl"><span class="cb1">using</span> System.Drawing;</pre><pre class="cl"><span class="cb1">using</span> System.Linq;</pre><pre class="cl"><span class="cb1">using</span> System.Text;</pre><pre class="cl"><span class="cb1">using</span> System.Windows.Forms;</pre><pre class="cl"><span class="cb1">using</span> System.Runtime.InteropServices;</pre><pre class="cl"> </pre><pre class="cl"><span class="cb1">namespace</span> PInvokeTesting</pre><pre class="cl">{</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">struct</span> <span class="cb2">FLASHWINFO</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">uint</span> cbSize;</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb2">IntPtr</span> hwnd;</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">uint</span> dwFlags;</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">uint</span> uCount;</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">uint</span> dwTimeout;</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">partial</span> <span class="cb1">class</span> <span class="cb2">Form13</span> : <span class="cb2">Form</span></pre><pre class="cl"> {</pre><pre class="cl"> [<span class="cb2">DllImport</span>(<span class="cb3">"kernel32.dll"</span>)]</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">static</span> <span class="cb1">extern</span> <span class="cb1">bool</span> AllocConsole();</pre><pre class="cl"> </pre><pre class="cl"> [<span class="cb2">DllImport</span>(<span class="cb3">"kernel32.dll"</span>)]</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">static</span> <span class="cb1">extern</span> <span class="cb1">bool</span> FreeConsole();</pre><pre class="cl"> </pre><pre class="cl"> [<span class="cb2">DllImport</span>(<span class="cb3">"User32.dll"</span>)]</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">static</span> <span class="cb1">extern</span> <span class="cb1">bool</span> FlashWindowEx(<span class="cb1">ref</span> <span class="cb2">FLASHWINFO</span> pfwi);</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">public</span> Form13()</pre><pre class="cl"> {</pre><pre class="cl"> InitializeComponent();</pre><pre class="cl"> <span class="cb1">this</span>.Activated += <span class="cb1">new</span> System.<span class="cb2">EventHandler</span>(<span class="cb1">this</span>.Form13_Activated);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">void</span> Form13_Activated(<span class="cb1">object</span> sender, <span class="cb2">EventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.StopFlashing();</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> button1_Click(<span class="cb1">object</span> sender, <span class="cb2">EventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> AllocConsole();</pre><pre class="cl"> <span class="cb2">Console</span>.WriteLine(<span class="cb3">"Writing this to a console from a Windows App."</span>);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> button2_Click(<span class="cb1">object</span> sender, <span class="cb2">EventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb2">Console</span>.WriteLine(<span class="cb3">"Press any key to close the console."</span>);</pre><pre class="cl"> <span class="cb2">Console</span>.ReadKey(<span class="cb1">true</span>);</pre><pre class="cl"> FreeConsole();</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> button3_Click(<span class="cb1">object</span> sender, <span class="cb2">EventArgs</span> e)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">this</span>.WindowState = <span class="cb2">FormWindowState</span>.Minimized;</pre><pre class="cl"> <span class="cb1">this</span>.Flash();</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> Flash()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb2">FLASHWINFO</span> pwfi = <span class="cb1">new</span> <span class="cb2">FLASHWINFO</span>();</pre><pre class="cl"> <span class="cb4">//assign the windows handle of our Form</span></pre><pre class="cl"> pwfi.hwnd = <span class="cb1">this</span>.Handle;</pre><pre class="cl"> <span class="cb4">//size of the struct. Needed for the unmanaged world to allocated correct number of bytes</span></pre><pre class="cl"> pwfi.cbSize = <span class="cb2">Convert</span>.ToUInt32(<span class="cb2">Marshal</span>.SizeOf(<span class="cb1">typeof</span>(<span class="cb2">FLASHWINFO</span>)));</pre><pre class="cl"> <span class="cb4">//number of times to blink. We want max possible</span></pre><pre class="cl"> pwfi.uCount = <span class="cb1">uint</span>.MaxValue;</pre><pre class="cl"> <span class="cb4">//the flash status. 2 = taskbar only</span></pre><pre class="cl"> pwfi.dwFlags = 2;</pre><pre class="cl"> </pre><pre class="cl"> FlashWindowEx(<span class="cb1">ref</span> pwfi);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">private</span> <span class="cb1">void</span> StopFlashing()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb2">FLASHWINFO</span> pwfi = <span class="cb1">new</span> <span class="cb2">FLASHWINFO</span>();</pre><pre class="cl"> pwfi.hwnd = <span class="cb1">this</span>.Handle;</pre><pre class="cl"> pwfi.cbSize = <span class="cb2">Convert</span>.ToUInt32(<span class="cb2">Marshal</span>.SizeOf(<span class="cb1">typeof</span>(<span class="cb2">FLASHWINFO</span>)));</pre><pre class="cl"> pwfi.uCount = <span class="cb1">uint</span>.MaxValue;</pre><pre class="cl"> pwfi.dwFlags = 0;</pre><pre class="cl"> </pre><pre class="cl"> FlashWindowEx(<span class="cb1">ref</span> pwfi);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> }</pre><pre class="cl">}</pre></div>
<br />Run the program and click the button3. You'll see the window minimize, and start blinking. As soon as you bring it back up, it'll stop flashing.
<br />
<br />This is just the tip of the iceberg with P/Invoke, but hopefully this gave you some idea as to what can be done.
<br />A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com0tag:blogger.com,1999:blog-5611706923356552090.post-29724896216217433182009-03-16T20:37:00.007-04:002009-03-16T22:44:20.848-04:00New Features in C# 3.0 / .NET 3.5 Part 3This is the third part of the New Features in C# 3.0 / .NET 3.5 series. Part 1 can be found <a href="http://crazorsharp.blogspot.com/2009/03/new-features-in-c-30-net-35-part-1.html">here</a> and Part 2 can be found <a href="http://crazorsharp.blogspot.com/2009/03/new-features-in-c-30-net-35-part-2.html">here</a>.<br /><br />The next thing I'd like to cover is a new keyword introduced in .NET 3.5 which is the "var" keyword. From<a href="http://msdn.microsoft.com/en-us/library/bb384061.aspx"> MSDN</a>:<br /><br /><blockquote style="font-style: italic;">Local variables can be given an inferred "type" of <span><span class="input">var</span></span> instead of an explicit type. The <span><span class="input">var</span></span> keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement. The inferred type may be a built-in type, an anonymous type, a user-defined type, or a type defined in the .NET Framework class library.</blockquote>In simple terms, when declaring a local variable, you no longer need to specify what type of variable it is on the left hand side of the assignment call. For example:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }</style><div class="cf"><pre class="cl"><span class="cb1"> int</span> x = 10;<br /></pre></div><br />is just the same as this:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }</style><div class="cf"><pre class="cl"><span class="cb1"> var</span> y = 10;</pre></div><br />It's important to note that this is NOT a dynamic type that's available in other languages like PHP or python. With dynamic types (which will be available in .NET 4.0) the compiler does NOT know at design time what Type the variable will be. It will be figured out at runtime. With C# type inference though, the compiler knows full well what the type will be. It can figure it out from what's on the right hand side. Now I know you're probably thinking "what's the point of this? how hard is it to just type a few extra letters?" Well, imagine if you have something like this:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: #2b91af; }.cb2 { color: blue; }</style><div class="cf"><pre class="cl"><span class="cb1">Dictionary</span><<span class="cb2">string</span>, <span class="cb1">List</span><<span class="cb1">StringBuilder</span>>> dictionary = <span class="cb2">new</span> <span class="cb1">Dictionary</span><<span class="cb2">string</span>, <span class="cb1">List</span><<span class="cb1">StringBuilder</span>>>();<br /></pre></div><br /><br />Well don't you think it'd be neater if we had this?<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"><span class="cb1">var</span> dictionary = <span class="cb1">new</span> <span class="cb2">Dictionary</span><<span class="cb1">string</span>, <span class="cb2">List</span><<span class="cb2">StringBuilder</span>>>();</pre></div><br />At first it may not seem like a big deal but you'll find yourself starting to use it quite often. The thing to point out though is that the "var" keyword can ONLY be used for variables that are local in scope. They can not be used for class level variables. This would NOT compile:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: green; }</style><div class="cf"><pre class="cl"><span class="cb1"> public</span> <span class="cb1">class</span> <span class="cb2">MyClass</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">var</span> myVariable = <span class="cb1">new</span> <span class="cb2">StringBuilder</span>(); <span class="cb3">//compile error</span></pre><pre class="cl"> <span class="cb1">public</span> MyClass()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">var</span> varIable = <span class="cb1">new</span> <span class="cb2">StringBuilder</span>(); <span class="cb3">//this is fine</span></pre><pre class="cl"> }</pre><pre class="cl"> }</pre></div><br />You're probably STILL thinking, "what's the use? Why bother??". Well, this leads me to the next new feature in .NET 3.5. The real reason these things were created was for something called "Anonymous Types". From <a href="http://msdn.microsoft.com/en-us/library/bb397696.aspx">MSDN</a>:<br /><br /><blockquote>Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to first explicitly define a type. The type name is generated by the compiler and is not available at the source code level. The type of the properties is inferred by the compiler. The following example shows an anonymous type being initialized with two properties called Amount and Message.</blockquote>Anonymous types allow you to create a new type on the fly. For example:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #a31515; }</style><div class="cf"><pre class="cl"><span class="cb1"> public</span> <span class="cb1">void</span> MyMethod()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">var</span> myNewObject = <span class="cb1">new</span></pre><pre class="cl"> {</pre><pre class="cl"> stringProperty = <span class="cb2">"Hello, World!"</span>,</pre><pre class="cl"> intProperty = 1337,</pre><pre class="cl"> boolProperty = <span class="cb1">false</span></pre><pre class="cl"> };</pre><pre class="cl"> }</pre></div><br />At this point, C# has actually created a new type for us with the read-only properties that we specified in our declaration of the Anonymous Type. Again, this type is only within the scope of this method, but we can now actually dot into myNewObject as if it were a real object from a concrete class. For example:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #a31515; }.cb3 { color: #2b91af; }.cb4 { color: green; }</style><div class="cf"><pre class="cl"><span class="cb1"> var</span> myNewObject = <span class="cb1">new</span></pre><pre class="cl"> {</pre><pre class="cl"> stringProperty = <span class="cb2">"Hello, World!"</span>,</pre><pre class="cl"> intProperty = 1337,</pre><pre class="cl"> boolProperty = <span class="cb1">false</span></pre><pre class="cl"> };</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb3">Console</span>.WriteLine(myNewObject.stringProperty); <span class="cb4">//output: "Hello, World!"</span></pre><pre class="cl"> <span class="cb3">Console</span>.WriteLine(myNewObject.intProperty); <span class="cb4">//output: 1337</span></pre><pre class="cl"> <span class="cb3">Console</span>.WriteLine(myNewObject.boolProperty); <span class="cb4">//output false</span></pre></div><br />And this is what Intellisense looks like:<br /><br /><div style="text-align: center;"><img style="width: 674px; height: 235px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg35pNN71y4ozw494Qt14nc2TOmCFLAb7k3Odab9z8Dopp4nLINo4cSrnRjSoCpqClYlZ802J3soWiNYLOLqF9KvjkBBSpCjbjYUGMh5kT02ij4U1e8N9hgd5v_lfJkiBV8imVentg-UBY/s400/intellisense_anonymous_type.GIF" alt="" /><br /></div><br />As you can see, Intellisense picks up all the properties of our Anonymous Type. The interesting thing here is that a concrete type is actually created for us by the compiler. By inspecting the IL this is what we find:<br /><br /><img style="width: 681px; height: 268px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZHsVF7XQt_oKTdDYz4sHtW167n21y6yw5Cfrme8bn4sDbEddRPcLN5k2ocQsexLDVi2jWzWf6PJftG4DPV_BECt_NT4D-Sn8nvJxDNzCLdQ3-LGOfQvbtnWAnlrAlmV1N6ucYDLEcAzo/s400/anontype_il.GIF" /><br /><br />What's really interesting here, is that if somewhere else in your app you have another Anonymous Type that looks just like this one, the C# compiler is smart enough to only create one class of that Type. It has to be the exact same set of parameters with the same name and in the exact order.<br /><br />To prove this, there's a known "hack" out there that allows you to actually return an anonymous type from a method (contrary to what I said before that Anonymous Types are only local in scope). Consider this:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #a31515; }</style><div class="cf"><pre class="cl"><span class="cb1"> public</span> <span class="cb1">object</span> MyMethod()</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">var</span> myNewObject = <span class="cb1">new</span></pre><pre class="cl"> {</pre><pre class="cl"> stringProperty = <span class="cb2">"Hello, World!"</span>,</pre><pre class="cl"> intProperty = 1337,</pre><pre class="cl"> boolProperty = <span class="cb1">false</span></pre><pre class="cl"> };</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">return</span> myNewObject;</pre><pre class="cl"> }</pre></div><br />Our same anonymous type as before, only now we're actually returning this from a method. Now, here's the cool part:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }</style><div class="cf"><pre class="cl"><span class="cb1"> public</span> T Cast<T>(<span class="cb1">object</span> obj, T type)</t></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">return</span> (T)obj;</pre><pre class="cl"> }</pre></div><br />A generic method that takes Object as a parameter, then an object of type T as the second parameter. It then casts obj to the type of T. Here's how we can now use this:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #a31515; }</style><div class="cf"><pre class="cl"><span class="cb1"> var</span> obj = MyMethod();</pre><pre class="cl"> <span class="cb1">var</span> myNewObj = Cast(obj, <span class="cb1">new</span> { stringProperty = <span class="cb2">""</span>,<br /> intProperty = 0, boolProperty = <span class="cb1">false</span> });<br /><br /></pre></div><br /><br />Now here's where we prove that C# only creates ONE class for that anonymous type. We passed in as the second parameter to the Cast method a new anonymous types with different values. However, since the parameters are the same and the order is the same, we can cast obj (the return value from our method) to the SAME TYPE as the new anonymous type. If C# created two separate classes, this would never work!<br /><br />This isn't my trick, and I wouldn't recommend using this in production code, but it gets the point across.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com1tag:blogger.com,1999:blog-5611706923356552090.post-61682796173053437582009-03-15T15:03:00.007-04:002009-03-15T17:38:09.099-04:00.Net Reflection Part 2. Loading Assemblies at runtime.<a href="http://crazorsharp.blogspot.com/2009/03/net-reflection-hey-look-i-can-see.html">In my first post about Reflection</a>, I gave a basic demo of what can be done using reflection. How you can access metadata about a class such as properties etc. In this post, I'd like to dig a bit deeper into Reflection and show the true power of Reflection and what can be accomplished.<br /><br />As you may or may not know, Visual Studio has many great addons that can be found across the web. Basically, Microsoft has an API that developers can code against, and then "plugin" their addons into Visual Studio. How is this accomplished? How does it know how to load the code I wrote into Visual Studio? The basic idea behind this is a simple Plugin System that can be accomplished using Reflection. I'll demonstrate the basic premise here to give you a simple understanding of how this all works. This post will be more of a tutorial kind of deal so follow along with me as I go through the steps and I explain them.<br /><br />Before we do any code, let me explain the basic idea of what we'll do. We're going to create an Interface that we'll call IPluginInterface which will have one simple get property called "Name". All "plugins" will have to implement this interface. At runtime, we will then look in a specific folder for any dll files that have types that implement this interface. If it does, then we know it's a plugin, and we can load it up into our app. May not make sense now, but bear with me. It'll all make sense once we start coding.<br /><br />OK, fire up Visual Studio and create a Console Application callaed "AssemblyLoadingDemo". Change the default namespace to: SetFocusDemo.Reflection.Demo. You should now see this:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cln { color: #2b91af; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"><span class="cln"> 1</span> <span class="cb1">using</span> System;</pre><pre class="cl"><span class="cln"> 2</span> <span class="cb1">using</span> System.Collections.Generic;</pre><pre class="cl"><span class="cln"> 3</span> <span class="cb1">using</span> System.Linq;</pre><pre class="cl"><span class="cln"> 4</span> <span class="cb1">using</span> System.Text;</pre><pre class="cl"><span class="cln"> 5</span> </pre><pre class="cl"><span class="cln"> 6</span> <span class="cb1">namespace</span> SetFocusDemo.Reflection.Demo</pre><pre class="cl"><span class="cln"> 7</span> {</pre><pre class="cl"><span class="cln"> 8</span> <span class="cb1">class</span> <span class="cb2">Program</span></pre><pre class="cl"><span class="cln"> 9</span> {</pre><pre class="cl"><span class="cln"> 10</span> <span class="cb1">static</span> <span class="cb1">void</span> Main(<span class="cb1">string</span>[] args)</pre><pre class="cl"><span class="cln"> 11</span> {</pre><pre class="cl"><span class="cln"> 12</span> </pre><pre class="cl"><span class="cln"> 13</span> }</pre><pre class="cl"><span class="cln"> 14</span> }</pre><pre class="cl"><span class="cln"> 15</span> }</pre></div><br />OK, for now we won't do anything in this project. Now Click on File -> New -> Project and select "Class Library". Call it "PluginInterface". Get rid of the default Class1.cs, and add a class called "IPluginInterface.cs". Then, add this code to the interface:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: gray; }.cb3 { color: green; }.cb4 { color: #2b91af; }</style><div class="cf"><pre class="cl"><span class="cb1">namespace</span> SetFocusDemo.Reflection.Contract</pre><pre class="cl">{</pre><pre class="cl"> <span class="cb2">///</span><span class="cb3"> </span><span class="cb2"><summary></summary></span></pre><pre class="cl"> <span class="cb2">///</span><span class="cb3"> This interface will need to be implemented by any class that wants to be a plugin</span></pre><pre class="cl"> <span class="cb2">///</span><span class="cb3"> in our Demo Plugin project.</span></pre><pre class="cl"> <span class="cb2">///</span><span class="cb3"> </span><span class="cb2"></span></pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">interface</span> <span class="cb4">IPluginInterface</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">string</span> Name { <span class="cb1">get</span>; }</pre><pre class="cl"> }</pre><pre class="cl">}</pre></div><br />Simple interface, doesn't do much really except it has the Name getter like we talked about. In a real life scenario, you would probably have multiple interfaces with multiple methods and properties, but again this is just a demo, so one is enough. Also, please note that I put this in the "SetFocus.Reflection.Contract" namespace.<br /><br />OK, now, let's actually create a few "Plugins". Basically they'll be classes that will implement this interface.First, let's create another Project. Click File -> New -> Project and create a Class Library called "Plugin Library". Then, right click on "References" and click "Add Reference". Select the Projects tab on top and click select the "Plugin Interface" assembly. Once that's done, remove the default "Class1.cs" and add a new class called "CustomPlugin1". Then, add this code:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"><span class="cb1">namespace</span> PluginLibrary</pre><pre class="cl">{<br /><style type="text/css">cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }</style><div class="cf"><pre class="cl"><span class="cb1"> using</span> SetFocusDemo.Reflection.Contract;</pre></div> <span class="cb1">public</span> <span class="cb1">class</span> <span class="cb2">CustomPlugin1</span> : <span class="cb2">IPluginInterface</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">string</span> Name</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">get</span> { <span class="cb1">return</span> <span class="cb3">"Custom Plugin 1"</span>; }</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl">}<br /><br /></pre></div> Doesn't do all that much, but it implements the IPluginInterface and just returns it's name. Now, add another class to this project, and call it "AnotherPlugin". Then add this code:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }</style><div class="cf"><pre class="cl"><span class="cb1">namespace</span> PluginLibrary</pre><pre class="cl">{<style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }</style><pre class="cl"><span class="cb1"> using</span> SetFocusDemo.Reflection.Contract;</pre> <span class="cb1">public</span> <span class="cb1">class</span> <span class="cb2">AnotherPlugin</span> : <span class="cb2">IPluginInterface</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">string</span> Name</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">get</span> { <span class="cb1">return</span> <span class="cb3">"Another Plugin"</span>; }</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl">}</pre></div><br />Same thing as before really. Another class that implements the same interface. Now, click on the Build menu and click "Build PluginLibrary". Once that's done, right click on the "Plugin Library" project on the right side in solution explorer and click on "Open Folder in Windows Explorer". Then, go to the Bin -> Debug folder and copy the "PluginLibrary.dll" file. Then, open your MyDocuments folder and paste it in there.<br /><br />OK, we finally have all the code set up to actually write our Plugin Loader. This is where the Reflection magic will happen. Go back to the first project that we called "AssemlyLoadingDemo". First, add a reference to the "Plugin Interface" project and add the using statement on top: "using SetFocusDemo.Reflection.Contract;" Add a new class and call it "PluginLoader.cs". This class will have one static method that will return an array of all the IPluginInterface objects it found and created. Here's the actual code of the class:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: green; }.cb4 { color: #a31515; }</style><div class="cf"><pre class="cl"><span class="cb1">using</span> System;</pre><pre class="cl"><span class="cb1">using</span> System.Collections.Generic;</pre><pre class="cl"><span class="cb1">using</span> System.Linq;</pre><pre class="cl"><span class="cb1">using</span> System.Text;</pre><pre class="cl"><span class="cb1">using</span> SetFocusDemo.Reflection.Contract;</pre><pre class="cl"><span class="cb1">using</span> System.IO;</pre><pre class="cl"><span class="cb1">using</span> System.Reflection;</pre><pre class="cl"> </pre><pre class="cl"><span class="cb1">namespace</span> SetFocusDemo.Reflection.Loader</pre><pre class="cl">{</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">class</span> <span class="cb2">PluginLoader</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">static</span> <span class="cb2">IPluginInterface</span>[] GetPlugins(<span class="cb1">string</span> directory)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">if</span> (<span class="cb2">String</span>.IsNullOrEmpty(directory)) { <span class="cb1">return</span> <span class="cb1">null</span>; } <span class="cb3">//sanity check</span></pre><pre class="cl"> </pre><pre class="cl"> <span class="cb2">DirectoryInfo</span> info = <span class="cb1">new</span> <span class="cb2">DirectoryInfo</span>(directory);</pre><pre class="cl"> <span class="cb1">if</span> (!info.Exists) { <span class="cb1">return</span> <span class="cb1">null</span>; } <span class="cb3">//make sure directory exists</span></pre><pre class="cl"> </pre><pre class="cl"> <span class="cb2">List</span><<span class="cb2">IPluginInterface</span>> plugins = <span class="cb1">new</span> <span class="cb2">List</span><<span class="cb2">IPluginInterface</span>>();</pre><pre class="cl"> <span class="cb1">foreach</span> (<span class="cb2">FileInfo</span> file <span class="cb1">in</span> info.GetFiles(<span class="cb4">"*.dll"</span>)) <span class="cb3">//loop through all dll files in directory</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb3">//using Reflection, load Assembly into memory from disk</span></pre><pre class="cl"> <span class="cb2">Assembly</span> currentAssembly = <span class="cb2">Assembly</span>.LoadFile(file.FullName); </pre><pre class="cl"> </pre><pre class="cl"> <span class="cb3">//Type discovery to find the type we're looking for which is IPluginInterface</span></pre><pre class="cl"> <span class="cb1">foreach</span> (<span class="cb2">Type</span> type <span class="cb1">in</span> currentAssembly.GetTypes())</pre><pre class="cl"> {</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">if</span>(!type.ImplementsInterface(<span class="cb1">typeof</span>(<span class="cb2">IPluginInterface</span>)))</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">continue</span>;</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb3">//Create instance of class that implements IPluginInterface and cast it to type</span></pre><pre class="cl"> <span class="cb3">//IPluginInterface and add it to our list</span></pre><pre class="cl"> <span class="cb2">IPluginInterface</span> plugin = (<span class="cb2">IPluginInterface</span>)<span class="cb2">Activator</span>.CreateInstance(type);</pre><pre class="cl"> plugins.Add(plugin);</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">return</span> plugins.ToArray();</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl">}</pre></div><br />There's alot of code here, I know and I'll do my best to explain. Before I do that though, two things to note. First, you'll see a using statment on top to System.Reflection. Secondly, you'll see this line of code: type.ImplementsInterface(typeof(IPluginInterface)) but that's an extension method I wrote. (For more on extension methods, see my blog post about them <a href="http://crazorsharp.blogspot.com/2009/03/new-features-in-c-30-net-35-part-1.html">here.</a>) Right click on the project and add a class called "TypeExtensions". Here's the code:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"><span class="cb1">using</span> System;</pre><pre class="cl"><span class="cb1">using</span> System.Collections.Generic;</pre><pre class="cl"><span class="cb1">using</span> System.Linq;</pre><pre class="cl"><span class="cb1">using</span> System.Text;</pre><pre class="cl"> </pre><pre class="cl"><span class="cb1">namespace</span> SetFocusDemo.Reflection.Loader</pre><pre class="cl">{</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">static</span> <span class="cb1">class</span> <span class="cb2">TypeExtensions</span></pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">public</span> <span class="cb1">static</span> <span class="cb1">bool</span> ImplementsInterface(<span class="cb1">this</span> <span class="cb2">Type</span> type, <span class="cb2">Type</span> interfaceType)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">return</span> type.GetInterfaces().Contains(interfaceType);</pre><pre class="cl"> }</pre><pre class="cl"> }</pre><pre class="cl">}</pre></div><br />Simple method that checks to see if a given type implements a specific interface.<br /><br />OK, now we can go back and explain what's going on here.<br /><br />The GetPlugins method takes a directory name as it's parameter indicating where we want to check for plugins. First we just do some sanity checking to make sure we don't get any Null Reference Exceptions:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: green; }</style><div class="cf"><pre class="cl"><span class="cb1"> if</span> (<span class="cb2">String</span>.IsNullOrEmpty(directory)) { <span class="cb1">return</span> <span class="cb1">null</span>; } <span class="cb3">//sanity check</span></pre><pre class="cl"> <span class="cb2">DirectoryInfo</span> info = <span class="cb1">new</span> <span class="cb2">DirectoryInfo</span>(directory);</pre><pre class="cl"> <span class="cb1">if</span> (!info.Exists) { <span class="cb1">return</span> <span class="cb1">null</span>; } <span class="cb3">//make sure directory exists</span></pre></div><br />Now we know our "info" object points to the directory we want to look for Plugins.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: #2b91af; }.cb2 { color: blue; }</style><div class="cf"><pre class="cl"><span class="cb1">List</span><<span class="cb1">IPluginInterface</span>> plugins = <span class="cb2">new</span> <span class="cb1">List</span><<span class="cb1">IPluginInterface</span>>();</pre></div><br />Here we just new up a List that will be used to add the plugins found and returned from the method.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }.cb3 { color: #a31515; }.cb4 { color: green; }</style><div class="cf"><pre class="cl"><span class="cb1">foreach</span> (<span class="cb2">FileInfo</span> file <span class="cb1">in</span> info.GetFiles(<span class="cb3">"*.dll"</span>)) <span class="cb4">//loop through all dll files in directory</span></pre><pre class="cl"> {</pre></div> Here we start enumerating all the files in the directory to find dll files. <span style="font-weight: bold;">Note: in a real world app, this can be dangerous. You're loading dll's into your app without really knowing that they're safe. In a real world, you'd load them into a seperate app domain, but that's out of the scope of this post. </span><br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: green; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"><span class="cb1"> //using Reflection, load Assembly into memory from disk</span></pre><pre class="cl"> <span class="cb2">Assembly</span> currentAssembly = <span class="cb2">Assembly</span>.LoadFile(file.FullName);<br /><br /></pre></div> Here we actually load the Assembly from the DLL file found. The Assembly class had many great methods on it which allows you to do all kinds of stuff at runtime. In our case, we'll just be looking thro<span style="font-family:georgia;">ugh th</span>e assembly to find a "Plugin":<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: green; }.cb2 { color: blue; }.cb3 { color: #2b91af; }</style><div class="cf"><pre class="cl"> <span class="cb1">//Type discovery to find the type we're looking for which is IPluginInterface</span></pre><pre class="cl"> <span class="cb2">foreach</span> (<span class="cb3">Type</span> type <span class="cb2">in</span> currentAssembly.GetTypes())</pre><pre class="cl"> {</pre></div> Now, we loop through all the Types found in the Assembly. GetTypes() returns an Array of all the Types found in that assembly. That includes classes, interfaces etc.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"> <style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"><span class="cb1"> if</span>(!type.ImplementsInterface(<span class="cb1">typeof</span>(<span class="cb2">IPluginInterface</span>)))</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb1">continue</span>;</pre><pre class="cl"> }<br /><br /></pre></div> </div>Here we look at the type to see if it implements our interface. The idea here is, if a class wants to be a plugin to our App, it MUST implement our IPluginInterface. If it doesn't it can't be a plugin, in which case we just "continue" and go to the next type found in the Assembly.<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: green; }.cb2 { color: #2b91af; }</style><div class="cf"><pre class="cl"><span class="cb1"> //Create instance of class that implements IPluginInterface and cast it to type</span></pre><pre class="cl"> <span class="cb1">//IPluginInterface and add it to our list</span></pre><pre class="cl"> <span class="cb2">IPluginInterface</span> plugin = (<span class="cb2">IPluginInterface</span>)<span class="cb2">Activator</span>.CreateInstance(type);</pre><pre class="cl"> plugins.Add(plugin);<br /><br /></pre></div> If we DID find a type that implements our interface, then we actually Create an Instance of that type using Activator.CreateInstance(type). We then cast it to the type of our interface, and add it to our list. Activator.CreateInstance is a really cool method that allows you to dynamically load up objects at runtime.<br /><br />Finally we clost up and return the List as an array:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }</style><div class="cf"><pre class="cl"><span class="cb1">return</span> plugins.ToArray();</pre></div><br />Ok, we now have all the code to give this a wirl. Go back to your Program.cs and in the main method add this code:<br /><br /><style type="text/css">.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; }.cl { margin: 0px; }.cb1 { color: blue; }.cb2 { color: green; }.cb3 { color: #2b91af; }.cb4 { color: #a31515; }</style><div class="cf"><pre class="cl"><span class="cb1">static</span> <span class="cb1">void</span> Main(<span class="cb1">string</span>[] args)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb2">//load plugins from MyDocuments. This is just a demo, in a real scenario, you'd use some</span></pre><pre class="cl"> <span class="cb2">//specific custom folder</span></pre><pre class="cl"> <span class="cb3">IPluginInterface</span>[] plugins = <span class="cb3">PluginLoader</span>.GetPlugins(</pre><pre class="cl"> <span class="cb3">Environment</span>.GetFolderPath(<span class="cb3">Environment</span>.<span class="cb3">SpecialFolder</span>.MyDocuments));</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb1">foreach</span> (<span class="cb3">IPluginInterface</span> plugin <span class="cb1">in</span> plugins)</pre><pre class="cl"> {</pre><pre class="cl"> <span class="cb3">Console</span>.WriteLine(<span class="cb4">"Plugin: \"{0}\" was found and loaded."</span>, plugin.Name);</pre><pre class="cl"> }</pre><pre class="cl"> </pre><pre class="cl"> <span class="cb3">Console</span>.ReadLine();</pre><pre class="cl"> }</pre></div><br />Basically, call our static method that loads up the plugins, loop through them and print out the name. Here's the output you should see:<br /><br /><span style="font-weight: bold;">Plugin: "Custom Plugin 1" was found and loaded.</span><br /><br /><span style="font-weight: bold;">Plugin: "Another Plugin" was found and loaded.</span><br /><br />What happened here? Basically, we copied our "Plugins" to our MyDocuments folder. When our PluginLoader went to look for Assemblies, it looked in the MyDocuments folder, and found our PluginLibrary.dll. It then loaded up the assembly and looked through the Types found there. It found "CustomPlugin1" and "AnotherPlugin". Then, it actually created instances of each of those classes and cast them as IPluginInterface. This is key! At design time, we have NO idea what the type we'll be. Any developer coding against our IPluginInterface API can create their own class that implements IPluginInterface. We have no clue what his class will be. What we DO know is that it will be of type IPluginInterface. Therefore, when we create an instance of it using Activator.CreateInstance, and cast it to the only type we know of which is IPluginInterface. Then, we can call the methods on our interface which in our cast is the Property "Name".<br /><br />This post turned out to be alot longer than I thought. There's alot happening here, so if you have any questions, seriosuly, email me at a.friedman07@gmail.com or post a comment here.A.Friedmanhttp://www.blogger.com/profile/17438995939632438979noreply@blogger.com0