Page 1 of 2 in the DevelopmentC category Next Page
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
This is not new, but something that helped me today. When debugging, you can see the types in scope in the auto’s window: This shows only the relevant information after expanding the view. One way of improving the experience is by implementing the 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. 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; }
}
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.
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: - Method Type Inference Changes, Part Zero
- Method Type Inference Changes, Part One
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.
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]
A nice series of posts about Covariance and Contravariance in a hypothetical future version of C# by Eric Lippert. - Covariance and Contravariance in C#, Part One
- Covariance and Contravariance in C#, Part Two: Array Covariance
- Covariance and Contravariance in C#, Part Three: Member Group Conversion Variance
- Covariance and Contravariance in C#, Part Four: Real Delegate Variance
- Covariance and Contravariance In C#, Part Five: Higher Order Functions Hurt My Brain
- Covariance and Contravariance in C#, Part Six: Interface Variance
- Covariance and Contravariance in C# Part Seven: Why Do We Need A Syntax At All?
- Covariance and Contravariance in C#, Part Eight: Syntax Options
- Covariance and Contravariance in C#, Part Nine: Breaking Changes
- Covariance and Contravariance in C#, Part Ten: Dealing With Ambiguity
Eric added another part:
-
Covariance and Contravariance, Part Eleven: To infinity, but not beyond
[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.
As you can see the difference between the text writer the binary writer are small, looking at the averages for all files.
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.
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.
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?
|