Give your C# class Initializer support0 Reacties

Would you like a to boost your class which hosts a collection, and utilize a cool C# language feature, which is collection initializer support?

For instance var myList = new List() {1,3,4} where {1,3,4} is the initializer.

The basic idea is to implement IEnumerable, and IEnumerator and the class must have an ‘Add’ method with the correct signature.

I made the class generic so you can initialize any array (ok, not for structs and simple types, but you modify a few things and that works too)

// our sample class for iteration feeding

public class Address
   {
       public string Street { get; set; }
       public string StreetNumber { get; set; }
       public string ZipCode { get; set; }
       public string City { get; set; }
   }
   public static class Program
   {
       static void Main()
       {
           var t = new ClassWithInitializerSupport

{
               new Address()
               {
                   Street = "Mainstr.",
                   StreetNumber = "1",
                   City ="London"
               },
              new Address()
               {
                   Street = "De Dam",
                   StreetNumber = "1",
                   City ="Amsterdam"
               },
               new Address()
               {
                   Street = "Mangostreet",
                   StreetNumber = "123",
                   City ="New York"
               }
           };
           foreach(var a in t)
           {
               Console.WriteLine("Street {0}, City {1}", a.Street, a.City);
           }

}

public class ClassWithInitializerSupport : IEnumerable, IEnumerator where T : class
   {
       public ClassWithInitializerSupport()
       {
           arr = (T[])Array.CreateInstance(typeof(T), 0);
           pos = -1;
       }
       private T[] arr;
       private int pos;
       public T Current => arr[pos];

       object IEnumerator.Current => arr[pos];

       public void Dispose()
       {

       }

       public IEnumerator GetEnumerator()
       {
           return this;
       }
       public void Add(T v)
       {
           var p = arr.Length;
           Array.Resize(ref arr, p + 1);
           arr[p] = v;
       }
       public bool MoveNext()
       {
           if (pos + 1 < arr.Length)
           {
               pos++;
               return true;
           }
           return false;
       }

       public void Reset()
       {
           pos = -1;
       }

       IEnumerator IEnumerable.GetEnumerator()
       {
           return this;
       }
   }

Howto: Check the case sensitive existence of a file0 Reacties

Sometimes, especially for files running on external FTP servers, where file names are case sensitive, a file named myFILE.html, is not the same file as myfile.html in the same path!

This function, can be used on an NTFS path for that purpose where File.Exists would fail, because it is case insensitive. (However, it does not enable you to have two files with just a different case in the same path)

///


/// Checks existance of file using a case sensitive compare
///

/// must be full filename
///
static bool FileExists(string file)

{

string pathCheck = Path.GetDirectoryName(file);

string filePart = Path.GetFileName(file);

      if (string.IsNullOrEmpty(pathCheck))

      {

      throw new ArgumentException("The file must include a full path", file);

      }

      string[] checkFiles = Directory.GetFiles(pathCheck, filePart, SearchOption.TopDirectoryOnly);

      if (checkFiles != null && checkFiles.Length > 0)

      {

            //must be a binary compare

            return Path.GetFileName(checkFiles[0]) == filePart;

       }

       return false;

}

 

Fill a dropdownlist using the current UICulture in (ASP.NET)0 Reacties

Just for educational purpose (as for myself as well :) ) I post this code.

Using this, a programmer can use a good practise, that is to use the culture information which is built in, into .NET instead of making that data him/herself.

based upon the following element in web.Config, the list will fill using the correct number of monthnames. It also keeps track of calendars, that have 13 months in some cultures.

<globalization uiCulture="nl-nl"/>

using System;

using System.Collections.Generic;

using System.Web;

using System.Linq;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Threading;

using System.Globalization;

public partial class _Default : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        int monthNumber = 0;

        CultureInfo ci = Thread.CurrentThread.CurrentUICulture;

        var myMonthnames = ci.DateTimeFormat.MonthNames

            .Take(ci.Calendar.GetMonthsInYear(DateTime.Today.Year)).Select(p => new { monthNo = ++monthNumber, monthName = p });

        ddlMonthnames.DataTextField = "monthName";

        ddlMonthnames.DataValueField = "monthNo";

        ddlMonthnames.DataSource = myMonthnames;

        ddlMonthnames.DataBind();

    }

}

<select name="ddlMonthnames" id="ddlMonthnames">

<option value="1">januarioption>

<option value="2">februarioption>

<option value="3">maartoption>

<option value="4">apriloption>

<option value="5">meioption>

<option value="6">junioption>

<option value="7">julioption>

<option value="8">augustusoption>

<option value="9">septemberoption>

<option value="10">oktoberoption>

<option value="11">novemberoption>

<option value="12">decemberoption>

select>

Performance and the future of LINQ expressions0 Reacties

I was wondering if writing well known C# (or VB.NET if you wish) code flow statements, such as for .. and foreach etc. are faster or slower compared to a generic expression.

The results are refreshing  Big Smile. At least using this simple array iteration. Array Iterations on millions of elements, of course, are not the the real life CPU eaters for an average ASP.NET website (eg), but consider this code.

There are three loops, doing the same.  (n.b.: I run a dual core i7200 CPU machine on Vista x64)

int ctr = 0;

var values = new string[1000000].

        Select(p => p = (ctr++).

        ToString()).

        ToArray();

List<int> intList;

intList = values.Select(p => int.Parse(p)).ToList();

int[] test1, test2, test3;

 // loop 10 times and calculate the average

test1 = new int[10];

test2 = new int[10];

test3 = new int[10];

for (int zz = 0; zz < 10; zz++)

{

    // our millisecond counter

    // it's ok to run this test several times to get an average score

    int start = Environment.TickCount;

    // convert the numeric array back to an int array

    intList = values.Select(p => int.Parse(p)).ToList();

    test1[zz] = Environment.TickCount - start;

    //now do the same but using a foreach iteration

    start = Environment.TickCount;

    intList = new List<int>();

    foreach (var p in values)

    {

        intList.Add(int.Parse(p));

    }

    test2[zz] = Environment.TickCount - start;

   //do it a last time, but with a for{} iteration

    // theoretically a this should save us an enumerator.

    start = Environment.TickCount;

    intList = new List<int>();

    int z = values.Length; 

    for (int x = 0; x < z; x++)

    {

        intList.Add(int.Parse(values[x]));

    }

    test3[zz] = Environment.TickCount - start;

    Console.WriteLine("{0}, {1}, {2}", test1[zz], test2[zz], test3[zz]);

   

}

Console.WriteLine("{0}, {1}, {2}", test1.Average(), test2.Average(), test3.Average());

Console.ReadKey();

To test this, run this code in release mode (plus Ctrl-F5, in Visual Studio).

x64 CPU platform results:
Test 1) 175ms
Test 2) 154 ms
Test 3) 155 ms

x86 CPU platform results:
Test 1) 198 ms
Test 2) 161 ms
Test 3) 169 ms

Test 1 uses an generic expression to 'cast'  a numeric string array to a List of type Int32.
Cute line, isn't it?
But unfortunately, as has been said, the LINQ expression, still is a bit slower than the non-linq versions.

How much slower when we deal with integer math and avoid any parsing overhead?

Now if we replace the int.Parse() statement by a silly integer operation, such as
intList = intvalues.Select(p => p -1 ).ToList(); we have to increase the loopcount to 10,000,000 to get the workload to any significance. Now we measure plain LINQ performance.

x64 results:
Test 1) 269 ms
Test 2) 125 ms
Test 3) 128 ms

x86 results:
Test 1) 276 ms
Test 2) 126 ms
Test 3) 121 ms

Conclusion:
I expect over time that compilers become more and more smarter and can optimize even better LINQ expressions. 
However, as we saw in the first example, int.Parse already flattened the results and the relative slowness of LINQ greatly.
Parsing and converting data in loops, is something we constantly do when we deal with XML and databases. So when the workload within the loop increases, the overhead of LINQ expressions quickly become no important factor. 

So, for shorter code, I would not hesitate to use those expressions as in Test 1.
In a real life business application, the performance of loops really does not determine the final user experience. It is (e.g.) how we access a database or other resources, such as XML.

It would be another story, if we e.g. were doing 3D math animations, where C++ would be an obvious choice.

 

HOWTO: [ADSI] Pinvoke the Wizard for a new Active Directory object0 Reacties

Wouldn't it be fun to create new active directory objects, while you even don't startup the MMC for active directory? No, don't be afraid that everybody including ‘nobody’ on your network -now- can do this

If the code below does not run on a domain controller, you first should install the adminpak.msi (or register dsadmin.dll and dsa.mcs) for on Windows 2003 that also can be installed on Windows XP.

And of course, Active Directory is -really- secure. If the calling code is not executed by someone with sufficient rights, it will fail.

So here we go and make yourself really -see- active directory!

(ps: I like writing unique code, as far as I can see, nobody did it yet, hey, don't forget to visit www.adccure.nl !)

static void Main()

{

IDsAdminCreateObject co = new DsAdminCreateObject() as IDsAdminCreateObject;
object nativedsObject = new DirectoryEntry("LDAP://cn=users,dc=yourdomain,dc=local").NativeObject;
co.Initialize(nativedsObject, null, "user");
object newObject = co.CreateModal(DsAdminCreateObject.GetDeskTopWindow());

}

[ComImport, Guid("53554A38-F902-11d2-82B9-00C04F68928B"),

InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

public interface IDsAdminCreateObject

{

///


/// Need to initialize before popping up the new object wizard
///

/// initialized dir object Container object eg: cn=users,DC=domain,dc=local
///
can be null, specifies original object if you want a copy!

/// contains "User", "group", "contact", "inetOrgPerson" etc
void Initialize( [MarshalAs(UnmanagedType.IDispatch)] object ADsContainerObj,
[MarshalAs(UnmanagedType.IDispatch), Optional(), DefaultParameterValue(null)] object ADsCopySource,
[MarshalAs(UnmanagedType.LPWStr)] string ClassName);

///


/// Returns native ActiveDirectory object
///

/// handle to parent window, specify 0 (mostly)
[return: MarshalAs(UnmanagedType.IDispatch)]
object CreateModal(IntPtr hwndParent);

}

 

///

/// Have our CLSID_DsAdminCreateObject be imported by .NET
///


[ComImport, Guid("E301A009-F901-11d2-82B9-00C04F68928B")]
public class DsAdminCreateObject

{

/// we just needed a pointer to a window, if you run this code within a Windows Form, you can fetch a handle to it and hand it over to CreateModal!
[DllImport("user32", EntryPoint = "GetDesktopWindow", ExactSpelling = true, SetLastError = false)]
public static extern IntPtr GetDeskTopWindow();
}

yummi! A new namespace! Let's have a look at ComTypes (NET 2.0)0 Reacties


I just had some COM interop work, and decided to use STGMEDIUM and
FORMATETC.
These structs, are necessary for many CLIPboard operations. But what draws my attention?
the MSDN says this:

typedef struct tagSTGMEDIUM

{

    DWORD tymed;

    [switch_type(DWORD), switch_is((DWORD) tymed)]

    union {

        [case(TYMED_GDI)]      HBITMAP        hBitmap;

        [case(TYMED_MFPICT)]   HMETAFILEPICT  hMetaFilePict;

        [case(TYMED_ENHMF)]    HENHMETAFILE   hEnhMetaFile;

        [case(TYMED_HGLOBAL)]  HGLOBAL        hGlobal;

        [case(TYMED_FILE)]     LPWSTR         lpszFileName;

        [case(TYMED_ISTREAM)]  IStream        *pstm;

        [case(TYMED_ISTORAGE)] IStorage       *pstg;

        [default] ;

    };

    [unique] IUnknown *pUnkForRelease;

}STGMEDIUM;

typedef STGMEDIUM *LPSTGMEDIUM;
As we all know, a union, in C++ is just a keyword which makes it's member variables start all at the same memory location. In a .NET struct, we can have the same result by using the following atribute: [StructLayout(LayoutKind.Explicit)]
For each structure member,. you now can specify an offset.
Our dear developers, decided for us, that we should not have that luxury of difficult choices having a struct with explicit layout, but let's not complain about this for now...
There is something -more- seriously wrong.

Have a look at the built in interop defintion (in the .NET 2.0 framework!)
(namespace System.Runtime.InteropServices.ComTypes)
public struct STGMEDIUM
{
public object pUnkForRelease;
public TYMED tymed;
public IntPtr unionmember;
}
 
After some crashes, I found that the definition, contains the correct members  at the wrong location!

As you can see, this defintion, is wrong and should be
public struct STGMEDIUM
{

public TYMED tymed;
public IntPtr unionmember;
public object pUnkForRelease;
}
 
A similar problem exists with FORMATETC. I'll not bother you with the details, but let's just post the correct defition. Next time, if you need these structs, don't use the one from the .NET 2.0 interop layer...

[StructLayout(LayoutKind.Sequential)]
public struct FORMATETC
{
   public short cfFormat;
   public IntPtr ptd;
   [
MarshalAs(UnmanagedType.U4)]
   public DVASPECT dwAspect; 
   public int lindex;
   [
MarshalAs(UnmanagedType.U4)]
   public TYMED tymed;
};

A C# implementation of DsCrackNames for a NameTranslate class, what about unsafe code? (update)0 Reacties

Have you ever tried to pinvoke a function, that returns a pointer to an array of structs? There's you can easily marshale them using safe C# code but if the code was not written already and you can't simply copy-paste that :), I promise to you, that you'll have to do a lot more work to get it done. unsafe code might be a quicker solution.

You could use unsafe code in the following situations:

a) You are not writing code or utilities, that might or will run in restricted environments, such as with an ISP environment. And ISPs (eg.) should not allow .NET to run third-party code that needs full-trust policies.
b) You have knowledge about pointers using C++
c) Your program will not be completely 'type safe', this is what some evangelists say, however, I don't see a flawless windows or webfarm if only everything were typesafe :).

Therefore, I propagate, that the biggest part, if not all, of your code, is type-safe. If some tiny utilities, are tested well and in favor of speed and power and possibilities, need to be type-unsafe, just go on.

If conditions have been considered, make your decision. Eventually stop reading now and wait for other postings :).

Such a candidate to be marked as unsafe, would be DsCrackNames, for the COM/automation world, it would be clever to instantiate the NameTranslate class which has an IDispatch interface (good for scripting as well).
Since ít's my hobby, to avoid easy solutions :) I wrote a unique (for the moment, I did not find another on the internet) wrapper for DsCrackNames which run nearly identical its earlier automation friend.

Let's have a look at the MSDN definition of this function.:
DWORD DsCrackNames(
  HANDLE hDS
,
  DS_NAME_FLAGS flags
,
  DS_NAME_FORMAT formatOffered
,
  DS_NAME_FORMAT formatDesired
,
  DWORD cNames
,
  LPCTSTR* rpNames
,
  PDS_NAME_RESULT* ppResult

);

Wow! this promises a lot of troubles, since PDS_NAME_RESULT is a pointer to a structure which contains an array of pointers to another sequential struct.

MSDN definition:
typedef struct
{
  DWORD cItems;
  PDS_NAME_RESULT_ITEM rItems;
} DS_NAME_RESULT,
*PDS_NAME_RESULT;

And here's the struct  rItems refers to...

typedef struct {
DWORD status;
LPTSTR pDomain;
LPTSTR pName;

} DS_NAME_RESULT_ITEM,
*PDS_NAME_RESULT_ITEM;


I do challence you, to write a 'safe' equivalent to it, I tried it, and believe me, the .NET framework does its stinking best to tell you that your attributes are not valid.

Of course, we understand that it simply is not possible  unless you jump to a MC++ solution or you use the definition from www.pinvoke.net which is requires a lot tricky code (no offense to anybody)... .

You cannot use attributes on the structure, and pass the stuff in one single call to the platform invoke and have the net framework do the actual marshaling for you.  You should create some looping work using Marshal.ReadInt32 (..) if you go for the 'safe' code solution .

I want to stress the point that safe platform invokes are not necessarily safer! They can leak memory as hell sorry, as well.

I've tried to use the [MarshalAs] attribute, but a having interop fill an array of IntPtrs inside a struct is not supported by the IL environment. Yes, you can try something like

struct DS_NAME_RESULT
{
        int cItems;
        IntPtr firstItem; //will work only if you crack one item or if you use Marshal.ReadInt32 etc code seen at pinvoke.net
}

Or try this... But now you have a managed array of IntPtr and that won't work as well.

struct DS_NAME_RESULT
{
        int cItems;
        IntPtr[] pDS_NAME_RESULT_ITEM; //won't be marshaled since the framework cannot create and marshale this array on the fly
}

and DS_NAME_RESULT ITEM would be like:

struct DS_NAME_RESULT_ITEM
{
public int status;
  [MarshalAs(UnmanagedType.LPWstr)]
public string pDomain;
  [MarshalAs(UnmanagedType.LPWstr)]
public string pName;
} ;

Let's see how easy you could write the solution set the 'unsafe'  attribute in spite of how disastrous this might sound.

Unsafe only allows for easy interop with unmaged IL code, this is a facto default with MC++, where you easily can use all those .h files, (windows.h, winbase.h etc) without having to retype all your DllImport statements or without having to copy them from http://www.pinvoke.net which often has untested declares. I could have use MC++ as well, but if you want to expose the assembly for reusage, you'll start to redefine all those Win32 enums and constants anyway. We have to learn to live with the border between managed and unmanged code.

Our 'unsafe' CSharp code, looks very much like a C++ implementation. In addition, it offers some improvements over the IADsNameTranslate interface (that you derive from NameTranslate, with Guid("b1b272a3-3625-11d1-a3a4-00c04fb950dc").

Some remarks about my style of programming: I really don't like ansi or Win9x compatible code. Screw it! :), as you can see, my declares favor Windows 2000 and higher. Also take in account, that this is not full proof & tested code.

Have fun using this code.

/* Copyright, Nierop Webconsultancy 2005 www.nieropwebconsult.nl

 * Use of this code, in your projects, is for your own risk.

 * If you modify the code, you send improvements back

 * If you copy the code, you won't remove the credits for the code

 */

using System;

using System.DirectoryServices;

using System.Runtime.InteropServices;

using System.DirectoryServices.ActiveDirectory;

using System.Data;

using System.ComponentModel;

 

 

namespace NameTranslate

{

    public enum ADS_NAME_INITTYPE_ENUM

    {

        ///

        /// Initializes a NameTranslate object by setting the domain that the object binds to.

        ///

        ADS_NAME_INITTYPE_DOMAIN = 1,

        ///

        /// Initializes a NameTranslate object by setting the server that the object binds to.

        ///

        ADS_NAME_INITTYPE_SERVER = 2,

        ///

        /// Initializes a NameTranslate object by locating the global catalog that the object binds to

        ///

        ADS_NAME_INITTYPE_GC = 3

    } ;

   

    public enum DS_NAME_FORMAT

    {

        DS_UNKNOWN_NAME = 0,

        DS_FQDN_1779_NAME = 1,

        DS_NT4_ACCOUNT_NAME = 2,

        DS_DISPLAY_NAME = 3,

        DS_UNIQUE_ID_NAME = 6,

        DS_CANONICAL_NAME = 7,

        DS_USER_PRINCIPAL_NAME = 8,

        DS_CANONICAL_NAME_EX = 9,

        DS_SERVICE_PRINCIPAL_NAME = 10,

        DS_SID_OR_SID_HISTORY_NAME = 11,

        DS_DNS_DOMAIN_NAME = 12

    } ;

 

    enum DS_NAME_FLAGS

    {

        ///

        /// Indicates that there are no associated flags

        ///

        DS_NAME_NO_FLAGS = 0x0,

        ///

        /// Performs a syntactical mapping at the client without transferring over the network.

        /// The only syntactic mapping supported is from DS_FQDN_1779_NAME to DS_CANONICAL_NAME or DS_CANONICAL_NAME_EX.

        /// DsCrackNames returns the DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING flag if a syntactical mapping is not possible.

        ///

        DS_NAME_FLAG_SYNTACTICAL = 0x1,

        ///

        /// Forces a trip to the domain controller for evaluation, even if the syntax could be cracked locally

        ///

        DS_NAME_FLAG_EVAL_AT_DC = 0x2,

        ///

        /// The call fails if the domain controller is not a global catalog server.

        ///

        DS_NAME_FLAG_GCVERIFY = 0x4,

        ///

        /// Enables cross forest trust referral.

        ///

        DS_NAME_FLAG_TRUST_REFERRAL = 0x8

    } ;

    public enum DS_NAME_ERROR

    {

        ///

        /// The conversion was successful.

        ///

        DS_NAME_NO_ERROR = 0,

        ///

        /// A generic processing error occurred.

        ///

        DS_NAME_ERROR_RESOLVING = 1,

        ///