Standing on the shoulders of giants. RSS 2.0
Page 1 of 2 in the DevelopmentC category Next Page
# Saturday, May 30, 2009

The new dynamic keyword and the DLR in C# 4 and the .NET Framework 4.0 can be used for good, as displayed by IronRuby, IronPython and several other samples.

But it’s much more to fun to use it for evil… by making Reflection simple.

In C# 3.0 invoking members through reflection, was kind of odd and certainly not very readable.

var employee = new Employee();
var members = employee.GetType().GetMember("age", MemberTypes.All,
                BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

((FieldInfo)members[0]).SetValue(employee, 30);

By wrapping all reflection magic in a dynamic object the same call would look like:

var employee = (new Employee()).AsDynamic();

employee.Name = "Paul van Brenk";
employee.Age = 30;

Console.WriteLine("Employee {0} is {1} years old.", employee.Name, employee.Age);

How this works is relatively easy.. by deriving a wrapper class from the new DynamicObject and overriding the TrySetMember and TryGetMember object to do the dirty work for you.

static class DynamicHelper
{
    public static dynamic AsDynamic(this T source)
    {
        return new DynamicReflection(source);
    }

    class DynamicReflection : DynamicObject
    {
        public DynamicReflection(T source)
            : base()
        {
            this.Source = source;
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            // find the member
            MemberInfo member;
            if (!TryFindMember(binder.Name, out member))
            {
                return false;
            }

            // we can only set values to fields and properties
            // using reflection
            switch (member.MemberType)
            {
                /* todo: check the type of the incoming value and the type of 
                  the property. */
                case (MemberTypes.Field):
                    ((FieldInfo)member).SetValue(Source, value);
                    return true;
                case (MemberTypes.Property):
                    ((PropertyInfo)member).SetValue(Source, value,/*ndex*/ null); // we don't support indexed properties
                    return true;
            }

            // didn't work
            return false;
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            // find the member
            MemberInfo member;
            if (!TryFindMember(binder.Name, out member))
            {
                result = null;
                return false;
            }

            // we can only set values to fields and properties
            // using reflection
            switch (member.MemberType)
            {
                /* todo: check the type of the incoming value and the type of 
                  the property. */
                case (MemberTypes.Field):
                    result = ((FieldInfo)member).GetValue(Source);
                    return true;
                case (MemberTypes.Property):
                    result = ((PropertyInfo)member).GetValue(Source,/*ndex*/ null); // we don't support indexed properties
                    return true;
            }

            // didn't work
            result = null;
            return false;
        }

        private bool TryFindMember(string name, out MemberInfo memberInfo)
        {
            // find the member
            var members = Type.GetMember(name, MemberTypes.All,
                                      BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            // more than 1 not supported for now
            if (members.Length != 1) { memberInfo = null; return false; }

            memberInfo = members[0];
            return true;
        }

        private Type Type { get { return typeof(T); } }

        public T Source { get; private set; }
    }
}

More info about implementing dynamic objects and behavior can be found on the DLR CodePlex site (esp. Getting Started with the DLR as a Library Author).

Source: Program.cs.txt

Saturday, May 30, 2009 7:53:08 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
C# | Visual Studio 2010
# Thursday, January 22, 2009

This is not new, but something that helped me today.

When debugging, you can see the types in scope in the auto’s window:

Default debugger

This shows only the relevant information after expanding the view. One way of improving the experience is by implementing the ToString() method.

ToString method

While this helps a lot, this means you can’t use the ToString method for something else. Luckily in VS 2008 the DebuggerDisplayAttribute was introduced, this allows you to achieve the same effect and more.

DebuggerDisplayAttribute

And the code:

[System.Diagnostics.DebuggerDisplay("Date:{Date}, Value:{Value}", Name="{Name}")]
class Item
{
    public string Name { get; set; }

    public DateTime Date { get; set; }

    public int Value { get; set; }
}
Thursday, January 22, 2009 5:31:28 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [0] - Trackback
C# | Codesnippet
# Saturday, August 30, 2008

Joe Duffy is building a custom threadpool on his blog, exploring the different trade-offs:

The first threadpool he designs in part 1 is a very simple one, using a naive algorithme. The second one in part 2 is more interesting, since this allows threads to 'steal' work from each other and tries to take advantage of work still being in the memory cache by using a LIFO (Last In First Out) algorithm.

Update:

Part 3 was posted some time ago, which integrates the queue from part 2 in the pool from part 1.

Saturday, August 30, 2008 9:34:45 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
C#
# Wednesday, June 18, 2008

Eric Lippert is starting a series of articles about future changes in the C# method type inference specification and the implementation. He plans to write about the following points:

  • What did method type inference look like in C# 2.0? Why was it inadequate for LINQ?
  • How did we attempt to modify and ultimately rewrite the specification for C# 3.0?
  • Where did we go subtly wrong in the specification and the implementation

The first 2 articles are posted on his blog:

  1. Method Type Inference Changes, Part Zero
  2. Method Type Inference Changes, Part One
Wednesday, June 18, 2008 2:42:25 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
C#
# Monday, April 07, 2008
class Program {
    static void Main(string[] args) {

        string[] strings = { "aa", "bb", "c", "dddd", "eeee", "f" };

        // use a class which implements IComparer
        // This works best when you want to re-use sorting logic
        //  or need to store state between using the comparer.
        Array.Sort(strings, new StringLengthComparer());

        // The following two methods only differ in syntax, both use a delegate.

        // use an anonymous method
        Array.Sort(strings, delegate(string x, string y) { return x.Length - y.Length; });

        // use a lambda expression
        Array.Sort(strings, (x, y) => x.Length - y.Length);

    }

    class StringLengthComparer : IComparer<string> {

        public int Compare(string x, string y) {
            return x.Length - y.Length;
        }
    }
}

Note: The array is sorted on the length of the strings, if you want to sort the strings in the array based on the content use an instance of the StringComparer class.

Monday, April 07, 2008 9:42:29 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
C# | Codesnippet
# Wednesday, March 26, 2008
# Monday, March 03, 2008

This class is an addition to the html- and url-encoding in the HttpServerUtility class. Where the methods in the base framework, only encode a limited number of characters. The classes in the AntiXss class encode everything, that is not explicitly allowed. These means that everything but the following characters are encoded in most cases: a-z, A-Z, 0-9, (comma), (period), (dash), (underscore) and (space). 

[download: Microsoft Anti-Cross Site Scripting Library V1.5]

Monday, March 03, 2008 5:55:07 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [0] - Trackback
C# | Security
# Friday, January 11, 2008
# Sunday, August 19, 2007

[Update: the results in this post about the performance of a memory stream, when changing the initial capacity are wrong. You can find the correct results in this new post.]

WCF (Windows Communication Framework) introduces additional XmlWriters for more efficient serialization of the messages send between nodes. These writers derive from the abstract XmlDictionaryWriter class and wrap the functionality of existing System.Xml. (For more information visit Justin Smith's post or watch Doug Purdy's COM326 presentation from PDC 05.

I was interested in the performance of the basic UTF-8 text writer and the binary writer for writing content heavy Xml. In this scenario an XmlDictionary won't give much benefit, since in my experience a dictionary will only reduce the size of the tags and not the actual content. More specifically I was interested in the difference in size and the speed of writing of xml files of various sizes.

On to the actual testing: I used the 138 feeds from my blogroll, that do not have a doctype in their feeds, since the XmlDictionaryWriter doesn't support writing those. After loading the feeds in an XmlDataDocument they are saved to the different streams and the size of the streams and the time it takes are written to a log-file for analyzing. Finally the whole process is repeated for a number of initial sizes for the MemoryStream (256 - 524288 in powers of 2).

The results: compression xml files makes them smaller, but it takes longer to write them.

Average performance graph

 As you can see the difference between the text writer the binary writer are small, looking at the averages for all files.

Split for file size chart

When looking at the bytes written / tick you'll see that the binary writer is generally faster for uncompressed files smaller than 8192 bytes and negligible slower for compressed files. Another thing to notice is that the writing speed increases for uncompressed streams as the files get bigger, while it drops a little for compressed streams. The fact that the writing speed drops for the biggest files is probably caused by the mem copy which occures when the memory stream has to increase it's capacity. 

initial capacity chart

 The initial capacity doesn't seems to influence the throughput of the memorystream in a significant way, but this may be related to the data I used to test.

[Download solution for VS 2008]

Notes:

1) According to the MSDN library the compression algorithm the DeflateStream uses is the same the GZipStream uses, so performance should be similar.

2) My data is not your data; you should always do your own testing and decide of the performance and the size are right for you.

Sunday, August 19, 2007 9:55:27 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
C# | XML
# Sunday, March 04, 2007

Although generally a bad idea [0], there is another problem. The System.Web.Caching.Cache doesn't call dispose on the items removed from the cache, causing a resource leak. To prevent this resource leak, add a CacheItemRemovedCallback in which you dispose of the object.

 

// add the item to the cache, note the callback

HttpRuntime.Cache.Add("myKey", myClass, null, DateTime.Now.AddSeconds(5), 
     Cache.NoSlidingExpiration, CacheItemPriority.Default, 
     new CacheItemRemovedCallback( OnRemoved ) );

// callback function

void OnRemoved( string key, object value, CacheItemRemovedReason reason ) {

     IDisposable disposable = value as IDisposable;
     if (disposable != null) {
          disposable.Dispose();
     }
}

 

[0] Should you really be caching an object containing unmanaged resources, which usually are scarce?

Sunday, March 04, 2007 5:58:57 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Codesnippet | C#
Ads
About
© Copyright 2010
Paul van Brenk
Sign In
newtelligence dasBlog 2.3.9074.18820
All Content © 2010, Paul van Brenk
DasBlog theme 'Business' created by Christoph De Baene (delarou)