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:
Object propertyValue = prop.GetValue(o, null); if (propertyValue != null && propertyValue.GetType().IsArray) { //if you need the type, here is how we get it, it's not used //in this example. Type arrayType = propertyValue.GetType().GetElementType(); object[] arr = propertyValue as object[]; for (int i = 0; i < arr.Length; i++) { // serialization logic goes here } } ...
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:
Object propertyValue = prop.GetValue(o, null); if (propertyValue != null && propertyValue.GetType().IsArray) { Array array = propertyValue as Array; foreach (var arrElement in array) { // serialization logic goes here } } ...
Straight forward, simple - makes me feel stupid.
layoutTable.Rows.Add ( ControlUtils.CreateRow ( EmployeeFieldLabels.ExternalCompanyName, { AllowMultipleSelection = false, RenderListHeader = false, CountryProviderId = locationPickerControl.ID, CountryProviderProperty = "SelectedCountryIsoCode"; }, false, EmployeeFieldTooltips.ExternalCompanyName, Page, CreateChildID("ExternalCompanyLabel"), ( externalCompanyValidator = new CompareValidator { ControlToValidate = CreateChildID("ExternalCompanyName"), Operator = ValidationCompareOperator.Equal, Type = ValidationDataType.Integer, ValueToCompare = "1", EnableClientScript = false, Display = ValidatorDisplay.Dynamic, ErrorMessage = string.Format(EmployeeManagerControlRes.ErrorValueRequired, EmployeeFieldLabels.ExternalCompanyName) } ) ) );
Check them out! http://msdn.microsoft.com/en-us/library/bb384062.aspx
Misusing this blog as my personal Post-It: http://www.mikeduncan.com/sqlite-on-dotnet-in-3-mins/
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 1.2I've just uploaded an new improved version of Push To Sync. Changelog:
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)
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?
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:
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
0.2 Alpha 2008-07-02 14:00 - 0.2
Download?
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!
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:
log4net.Config.XmlConfigurator.Configure();
once to initialize the log4net stack
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> </configSections> <log4net debug="true"> <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender,log4net" > <param name="File" value="Debug.log" /> <param name="AppendToFile" value="true" /> <maximumFileSize value="10MB" /> <maxSizeRollBackups value="2" /> <layout type="log4net.Layout.PatternLayout,log4net"> <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] <%X{auth}> - %m%n" /> </layout> </appender> <root> <priority value="ALL" /> <appender-ref ref="LogFileAppender" /> </root> </log4net> </configuration>
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)
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:
<param name="File" value="${SystemDrive}\Debug.log" />
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:
string someComplexQuery = @"select ... from ..."; IQuery sqlQuery = sessionFactory.GetCurrentSession().CreateSQLQuery(someComplexQuery). AddScalar("Id", NHibernateUtil.Int32). AddScalar("Firstname", NHibernateUtil.String). AddScalar("Lastname", NHibernateUtil.String).SetResultTransformer( IList<Person> people = sqlQuery.List<Person>(); foreach (Person person in people) { // ... }
class Person { private long id; private string firstname; private string lastname; public long Id { get { return id; } set { id = value; } } public string Firstname { get { return firstname; } set { firstname = value; } } public string Lastname { get { return lastname; } set { lastname = value; } } }