.NET

warning: Creating default object from empty value in /home/pulsar/webroot/htdocs/modules/taxonomy/taxonomy.pages.inc on line 33.

Accessing Arrays in .NET/c# via Reflection

Yesterday I was implementing a generic serializer (for logging purposes). While there is a good number of XML serializers available for .NET - none of them was meant to be used for only the purpose of reading. That means, I would not need deserialization but only some nice human readable output.

Anyway, thats not the point here. What took me about an hour to figure out is how to handle arrays (of natives) via reflection. I kinda feel stupid, but let me show you what i tired:

  1. Object propertyValue = prop.GetValue(o, null);
  2. if (propertyValue != null && propertyValue.GetType().IsArray)
  3. {
  4. //if you need the type, here is how we get it, it's not used
  5. //in this example.
  6. Type arrayType = propertyValue.GetType().GetElementType();
  7. object[] arr = propertyValue as object[];
  8. for (int i = 0; i < arr.Length; i++)
  9. {
  10. // serialization logic goes here
  11. }
  12. }
  13. ...

While this might work perfectly for arrays of "real" objects such as string[] - it will fail when your array is composed of native objects such as long[]. The cast to object[] will get you a nice null reference. Yummy.

After that I've been looking for Array.ForEach() which was pretty interesting, but did not really help due to it's generic nature. The solution was much simpler in the end, it just did not cross my mind to cast the propertyValue to Array - sometimes .NET can be pretty mysterious in terms of Autoboxing. Here is how it should be done:

  1. Object propertyValue = prop.GetValue(o, null);
  2. if (propertyValue != null && propertyValue.GetType().IsArray)
  3. {
  4. Array array = propertyValue as Array;
  5. foreach (var arrElement in array)
  6. {
  7. // serialization logic goes here
  8. }
  9. }
  10. ...

Straight forward, simple - makes me feel stupid.

Why I Love Local Initializers...

  1. layoutTable.Rows.Add
  2. (
  3. ControlUtils.CreateRow
  4. (
  5. EmployeeFieldLabels.ExternalCompanyName,
  6. new ExtCompanyPickerControl(CreateChildID("ExternalCompanyName"))
  7. {
  8. Customizer = new ExtCompanyCustomizer(MedaSession),
  9. AllowMultipleSelection = false,
  10. RenderListHeader = false,
  11. CountryProviderId = locationPickerControl.ID,
  12. CountryProviderProperty = "SelectedCountryIsoCode";
  13. },
  14. false,
  15. EmployeeFieldTooltips.ExternalCompanyName,
  16. Page,
  17. CreateChildID("ExternalCompanyLabel"),
  18. (
  19. externalCompanyValidator = new CompareValidator
  20. {
  21. ControlToValidate = CreateChildID("ExternalCompanyName"),
  22. Operator = ValidationCompareOperator.Equal,
  23. Type = ValidationDataType.Integer,
  24. ValueToCompare = "1",
  25. EnableClientScript = false,
  26. Display = ValidatorDisplay.Dynamic,
  27. ErrorMessage = string.Format(EmployeeManagerControlRes.ErrorValueRequired, EmployeeFieldLabels.ExternalCompanyName)
  28. }
  29. )
  30. )
  31. );

Check them out! http://msdn.microsoft.com/en-us/library/bb384062.aspx

SQLite, nHibernate and .NET

Misusing this blog as my personal Post-It: http://www.mikeduncan.com/sqlite-on-dotnet-in-3-mins/

User Management with Active Directory

The last 2 days I've been working on a concept paper for a project. One aspect covers user management using an active directory.

At the first glance, everything looks easy. One would think AD is just another LDAP server - no worries here. It turns out, AD has a lot of hidden constraints and expect you do things a certain way. For instance, if you want to add a user to a specific group, you are not going to update the user's "memberOf" LDAP attribute. This is read only; you will need to add that user to the group LDAP node. This is just one and quite straight forward example how AD can be a pain in the arse if you have no idea about the internals.

Luckily the guys over at http://en.csharp-online.net/ have assembled a damn good article about all daily tasks you will encounter if you are going to automate some user administration tasks using the Active Directory as your backend. Head over here: http://en.csharp-online.net/User_Management_with_Active_Directory%E2%80%...

I have also stumbled across a wrapper library which abstracts all the LDAP / DirectoryEntry specific calls and focuses on user- and group-centric API: http://www.dotnetactivedirectory.com/ - I have no idea yet if this one is good or not, I guess I will find out soon since I plan to cut down the development times by 2 Days and use this API instead.

update
After looking into the free (lite) version of .NET Active Directory wrapper, I am not so sure about purchasing a license anymore. 400 or 1000 bucks a a pretty hefty price tag for a software not being in development anymore (as it seems, last update 2007) and consisting only from one pseudo class. It can hanlde only one AD connection due to static (!) fields for login and password. Furthermore it does not persist a connection to the AD but re-creates a new Directry Entry with each operation - now do some mass operations on say... 5k users by assigning them to a AD groups or something.  I suppose it will be still more expensive for the project for me to code the mini-api, but after considering those facts, I might be better off. Especially when it comes to multiple AD servers and support requests I might get for this particular module. Geez! Where do ppl learn coding!? I guess good marketing and price tags not reflecting the code quality can still compensate it

Push To Sync updated to 1.2

Push To Sync 1.2Push To Sync 1.2I've just uploaded an new improved version of Push To Sync. Changelog:

  • [Feature] Time prediction based on average transfer speed 
  • [Feature] Shows the current transfer speed using a nice looking graph
  • [Bugfix] Fixed some issues with file timestamp handling when synchronizing to a linux samba share.
Download available here.

Sharepoint STSADM Extensions which will save your life!

If you are into Sharepoint-Development you will appreciate the STSADM Custom Extensions made by Gary Lapointe: http://stsadm.blogspot.com/2007/08/stsadm-commands_09.html

In our case they saved us a lot of troubles we had when moving a Sharepoint Site Collection to a new server while preserving the Variations which have been created before.

One of the commands we have been toying with was "gl-fixvariationrelationships". Since the sources to all of these extensions are available to download for free, I could even get this one working for a Variation root other than "/" by modifying the sources a tiny bit. If you run into the same situation feel free to grab my Version of the FixVariationRelationships Class over here or here (can't get drupal to ignore HTML validation for Geshi-Nodes editing)

 

Export an Outlook Folder to a Filesystem-Folder

Here is a small tool I wrote (well, rather hacked) which might come handy for some of you. Sourcecode is included so you might want to make it even fancier and do whatever comes to your mind with it.

OutlookFolderExporter 0.3 Beta

What does it do?
Export an Outlook folder containing E-Mail Messages to a physical filesystem folder. Message by message.

Requirements?

  • Outlook 2007
  • NET 2.0 Framework
  • Visual Studio 2007 (optional)


Why?
Someone asked me if I knew a tool or a way to do this. From what I understand he was about to share such messages using a Windows-Share. I know there are better ways to achieve this, provided you are using an Exchange-Server - but for some reason it did not work out for them.

Limitations?
Plenty, this is a really quick hack:

  • Supports only mail messages (no contacts, appointments etc)
  • Can export only one folder (no recursion) at a time
  • Developed and tested against Outlook 2007 (12.0) - no idea if this will even work for previous versions of Outlook. I suppose not.
  • Won't cook any coffee yet.
Obligatory Screenshot?


Usage?
You will need to know the path to your Outlook folder you would like to have exported. The root folder presumed by this applicationis the root folder of your default Outlook acccount. Beneath it you should have folders like Inbox, Contacts etc. To export all messages of the default inbox folder one would use "/Posteingang/" in the German version of Outlook. Must be something like "Inbox" for English Users I think. Another example would be "/Sent-Items/Archive" which would export the Archive folder which you have might created in the Sent-Items parent Folder.

License?
Public domain, check the "License.txt" in the sources package for further details.

History

0.3 Beta: 2008-07-02 20:40 0.3

  • Inbox->first folder restriction removed - You can export any account folder now.
  • Target directory might be created on demand.

0.2 Alpha 2008-07-02 14:00 - 0.2

  • Added an installer (otherwise we are missing some interop-libraries)
  • Repackaged, Sources will be also installed.

Download?

Debug, Log and Tail on Steroids

Sometimes I do really wonder why some great tools remain silent and hidden from the public for such a long time. The guys over at codeproject featured an article about the "TraceTool". Describing it with "yet another log viewer" won't do any justice. Just head over to the article and glance over it. It's able to interface with the most common logging frameworks such as .NET's native, log4net/log4j, NT System Evenlog and plain files.

I must admit I did not try it yet. Will do next week when I'm back in the office - I don't really feel like I want to be coding this weekend. But just reading the specs and howtos on the codeproject site blew my mind. Looks like a jewel, smells like a jewel... might be one!

Setup Log4Net for a project in less than 2 minutes

Sometimes documentation is plain anoying. I've been using log4j since ... I don't know, maybe 5-6 years? The setup was as simple as dropping a log4j.xml into the class path and using the logger right away.

Log4Net ist not really much more complicated, but it requires a little bit more attention. Here is what you need to start logging via log4net in less than 2 minutes:

  • Grab the log4net zip over at: http://logging.apache.org/log4net/download.html
  • Copy the log4net.dll (for instance bin\net\2.0\release in the zip archive) into your project. Ignore the other zip content if you don't care.
  • Add the library reference
  • Create an App.Config file using the big xml chunk provided below
  • Call log4net.Config.XmlConfigurator.Configure(); once to initialize the log4net stack
  • Done
  1. <?xml version="1.0" encoding="utf-8" ?>
  2.  
  3. <configuration>
  4.  
  5. <configSections>
  6. <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  7. </configSections>
  8.  
  9. <log4net debug="true">
  10. <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender,log4net" >
  11. <param name="File" value="Debug.log" />
  12. <param name="AppendToFile" value="true" />
  13. <maximumFileSize value="10MB" />
  14. <maxSizeRollBackups value="2" />
  15. <layout type="log4net.Layout.PatternLayout,log4net">
  16. <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] &lt;%X{auth}&gt; - %m%n" />
  17. </layout>
  18. </appender>
  19. <root>
  20. <priority value="ALL" />
  21. <appender-ref ref="LogFileAppender" />
  22. </root>
  23. </log4net>
  24.  
  25. </configuration>
some hints and tips to make your life easier:

Here is a pretty elegant way to obtain a logger with the category automatically set to the current class - (there is no equivalent to this in Java by the way - at least not for static fields)

  1. private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

The Logfile will be created next to the executable. Oh, and just in the case you did not know, you can use system envoronment variables in the App.config. For instance you could be foolish (or lazy if you prefer) and log directly onto the Windows system drive:

  1. <param name="File" value="${SystemDrive}\Debug.log" />

Using native SQL in nHibernate

Today I ran into a situation in a nHibernate based project where I needed to execute a very specialized query. Using HQL was rather not practical since I had to query tables which were not "directly" mapped to entities.

So, if you need execute queries behind nHibernate's back and map the results to a Bean / Object not specified in the mappings, You might come up with a solution like this:

  1. string someComplexQuery = @"select ... from ...";
  2.  
  3. IQuery sqlQuery =
  4. sessionFactory.GetCurrentSession().CreateSQLQuery(someComplexQuery).
  5. AddScalar("Id", NHibernateUtil.Int32).
  6. AddScalar("Firstname", NHibernateUtil.String).
  7. AddScalar("Lastname", NHibernateUtil.String).SetResultTransformer(
  8. Transformers.AliasToBean(typeof(Person)));
  9.  
  10. IList<Person> people = sqlQuery.List<Person>();
  11. foreach (Person person in people)
  12. {
  13. // ...
  14. }

For a good measure, here is the Person class:
  1. class Person
  2. {
  3. private long id;
  4. private string firstname;
  5. private string lastname;
  6.  
  7. public long Id
  8. {
  9. get { return id; }
  10. set { id = value; }
  11. }
  12.  
  13. public string Firstname
  14. {
  15. get { return firstname; }
  16. set { firstname = value; }
  17. }
  18.  
  19. public string Lastname
  20. {
  21. get { return lastname; }
  22. set { lastname = value; }
  23. }
  24. }

Works like a breeze, /me likes!

Syndicate content