Anonymous Types are Internal, C# 4.0 Dynamic Beware!

by ashic 26. May 2010 14:10

C# 4.0 has introduced the dynamic keyword. You can declare a variable as dynamic and regardless of what can be inferred at compile time, you can access any properties and call any methods and your code will still compile. Resolving of those properties and methods will be done at runtime. If at runtime, they aren't found, you'd get a runtime exception. If they are found, your code will run fine.

An Example

Consider a class called Person that has a property called Name. Consider the following piece of code:



Person p = new Person { Name = "John" };
object o = p;
dynamic d = o;
Console.WriteLine(d.Name);

On line 2, we're assigning p to an object reference o. Before C# 4.0, if you wanted to get the value of o's Name (and it does have a Name, since we know we assigned a Person object to o) you would have had to resort to reflection. With C# 4.0 however, we can use a dynamic variable like we did on line 3, and simply access the Name property on the dynamic variable. This program would compile fine, but it would require that the object assigned to d must (at runtime) have a property called Name. If it doesn't, it'll throw an exception.

So basically, we can assign a dynamic variable with any object and call properties and methods we expect it to have and it should run fine. Right? Not quite.

The Problem

The dynamic approach has one limitation – it must know the type of object it's dealing with. This isn't a problem for most cases, but it can be an issue when dealing with anonymous types. Let's get started building the project so you can see what I mean.

The Project

Create a basic .Net 4.0 console application called DynamicTest. Add a class library called ClassLibrary1 to the solution. Make class1.cs look like this:



namespace ClassLibrary1
{
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    } 

    public class Repository
    {
        Person _person = new Person { Name = "Adam", Age = 21 };
       
        public object GetPerson()
        {
            return _person;
        }

        public object GetPersonWrappedInAnonymousType()
        {
            return new { Person = _person };
        }
    }
}

We have a repository that has two methods. One simply returns a person as an object while the other wraps it in an anonymous type and returns an instance of that anonymous type. Going back to the main project's Program.cs, add the following code:



class Program
{
    static void Main(string[] args)
    {
        new Program().Run();
    }    

    private void Run()
    {
        var rep = new Repository();

        dynamic data = rep.GetPerson();
        Console.WriteLine(data.Name); 

        dynamic data2 = rep.GetPersonWrappedInAnonymousType();
        Console.WriteLine(data2.Person.Name);
    }
}



That looks simple enough. data and data2 are both dynamic variables. As such, their Name and Person.Name properties will be resolved at runtime. The program compiles fine, but when we run it, we get this:

Adam

Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'obj
ect' does not contain a definition for 'Person'
   at CallSite.Target(Closure , CallSite , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T
0 arg0)
   at DynamicTest.Program.Run() in F:\MyTests\C#\DynamicTest\DynamicTest\Program
.cs:line 24
   at DynamicTest.Program.Main(String[] args) in F:\MyTests\C#\DynamicTest\Dynam
icTest\Program.cs:line 13
Press any key to continue . . .

How come? The call to data.Name resolved fine, but the call to data2.Person failed. The error message states that the Person property could not be found at runtime. We can obviously see by looking at the code that data2 most definitely has a Person property and that in turn has a Name property. [And if you don't trust your eyes, you can run in debug mode, set a breakpoint just after data2 is initialized and if you use the watch window to view the properties of data2, you'll see that data2 does indeed have a data2.Person property but if you type in "data2.Person" in the watch window, you'll get the same exception…magic!]. So what gives?

Explanation

The reason the call to data2.Person fails is that the type information of data2 is not available at runtime. The reason it's not available is because anonymous types are not public. When the method is returning an instance of that anonymous type, it's returning a System.Object which references an instance of an anonymous type -  a type who's info isn't available to the main program. The dynamic runtime tries to find a property called Person on the object, but can't resolve it from the type information it has. As such, it throws an exception. The call to data.Name works fine since Person is a public class, that information is available and can be easily resolved.

This can affect you in any of the following cases (if not more):

1. You're returning a non-public, non-internal type using System.Object.
2. You're returning a non-public, non-internal derived type via a public Base type and accessing a property in the derived type that's not in the base type.
3. You're returning anything wrapped inside an anonymous type from a different assembly.

i.e. you need to be able to access the type info for the object at the point where its property / method is being resolved at runtime.

Solution

The solution is actually quite simple. All we have to do is open up AssemplyInfo.cs of the ClassLibrary1 project and add the following line to it:


[assembly:InternalsVisibleTo("DynamicTest")]


What this does is allow the main project to "look into" the internal types of ClassLibrary1. This means the dynamic runtime can find the type information of the anonymous type being returned and data2.Person.Name resolves perfectly. Anonymous types are internal. Adding that piece of code makes the type information "visible" to our main project.

Drawback

As you can see, the solution means you actually have to have control over the class library's source code for this to work. If you don't, then I guess you'd need to resort to good old fashioned reflection.

Application

This approach can come in handy for unit testing. You would expose the internal types of the assembly under test to the tests, and as such should be able to take advantage of the dynamic functionality of C# 4.0 when evaluating results from methods that return anonymous types.

Source

download

Shout it kick it on DotNetKicks.com

---------------------------------------------------------

Questions  and comments relating to this article are welcome. Comments completely unrelated to the article and posted with the sole intention of putting your link here are not.

If you spam, your comment will not be approved, will be deleted and your IP blocked. I maintain my site almost daily and such comments – even if they pass the spam filter – will get removed as soon as possible. If this gets too tedious, I may disable comments entirely. Please don't ruin it for everybody else.

---------------------------------------------------------

Share or Bookmark this post…
  • Facebook
  • DotNetKicks
  • Digg
  • LinkedIn
  • Technorati
  • del.icio.us
  • Google
  • Live
  • Tumblr
  • msdn Social
  • Ping.fm
  • Reddit
  • Slashdot
  • StumbleUpon
  • TwitThis
Tags: , ,
Categories: C# | .NET

Fetching a Property Value via Reflection

by ashic 10. May 2010 21:31

Reflection is a method by which we can use metadata at runtime to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties. It has many uses, ranging from allowing usage of attributes to creating instances of dynamically generated classes and using them. You can even use reflection to read and modify private member variables of an object. Today, we're going to look at a very simple example which will allow us to read the value of a public property given an instance.

The Class

Let's take a very simple class:



namespace MyNamespace
{
    public class MyClass
    {
        public int MyProperty { get; set; }
    }
}

Note, that I've put it in a separate namespace to show that it's easy to deal with this when using reflection.

The Runner

We'll run everything in a very simple console application:



public class Program
{
    static void Main(string[] args)
    {
        new Program().Run();
    }

    private void Run()
    {
        MyClass o = new MyClass { MyProperty = 25 };
        object value = GetPropertyValue(o, "MyProperty");
        Console.WriteLine(value);
    }
}

We're basically creating an instance of MyClass and passing the instance and the string "MyProperty" to a method called GetProperty. The method is returning an object (which we could have cast to anything we needed). We're passing the returned object to Console.WriteLine.

The Method

This is where we use reflection to find the value of the "MyProperty" property given an instance. Add the following method to the class:



private object GetPropertyValue(object o, string propertyName)
{
    Type type = o.GetType();
    PropertyInfo info = type.GetProperty(propertyName);
    object value = info.GetValue(o, null);
    return value;
}

We're getting the type information by calling GetType() on the object. Next, we call GetProperty() on the type information. Note, this only gives us information about the property and not the property itself. We then have to call GetValue() on the property information passing in the instance from which to get the actual value.

And that's all it takes :)

PS: You'll need a reference to System.Reflection to use Reflection.

PPS: Yes, this is a very very simple example of using reflection, but I found quite a few questions over at the forums today that would be answered by this. We all have to start somewhere, right?

Share or Bookmark this post…
  • Facebook
  • DotNetKicks
  • Digg
  • LinkedIn
  • Technorati
  • del.icio.us
  • Google
  • Live
  • Tumblr
  • msdn Social
  • Ping.fm
  • Reddit
  • Slashdot
  • StumbleUpon
  • TwitThis
Categories: .NET | ASP.NET | C#

How to use Session values in an HttpHandler

by ashic 18. September 2008 03:30

When writing a custom HttpHandler, by default you have no access to the Session object. Doing something like HttpContext.Current.Session also returns null. The workaround is quite simple:

Reference the System.Web.SessionState namespace:

using System.Web.SessionState;

 ...and decorate the handler with either the IRequiresSessionState attribute:

public class MyHandler:IHttpHandler, IRequiresSessionState 

or the IReadOnlySessionState attribute:

public class MyHandler:IHttpHandler, IReadOnlySessionState

with the latter giving read only access to the seesion object.

 

Hope that helps.

 

EDIT: As pointed out...IReadOnlySessionState and IRequiresSessionState are not attributes, but empty interfaces. This is pretty apparent from the fact that we're not decorating the handler, rather the handler implements the interface [and since it's an empty interface, we don't need to implement anything to do so]. Late night blogging can lure the fingers to strange routes on the keyboard, it seems 8)

Share or Bookmark this post…
  • Facebook
  • DotNetKicks
  • Digg
  • LinkedIn
  • Technorati
  • del.icio.us
  • Google
  • Live
  • Tumblr
  • msdn Social
  • Ping.fm
  • Reddit
  • Slashdot
  • StumbleUpon
  • TwitThis
Categories: .NET | ASP.NET

HTML Comments, Other Comments and Some VS Tips

by ashic 1. September 2008 21:50

 

I just found out something really weird about HTML comments. Apparently, according to standards, you can't do this:

<!--  comment ------------------------ -->

That is, you can't put two or more ‘-‘s inside a comment. It works as expected in IE7, but it breaks down horribly in FireFox. FireFox simply renders the comment to the user, which is pretty useless as that's not what comment are for!!. The standards "recommend" developers to not put two or more consecutive ‘-‘s inside an html comment. Now, that's weird. If there are specific delimeters like <!-- and  -->, then I should be able to use any part of those delims (but not the whole) inside a comment, shouldn't I?

Since, we're in the vicinity of comments, let's look at some for reference:

HTML: <!-comment -->

C#: //single line comment

/* multiline comment */

VB.NET: ‘single line comment

SQL: /* multiline comment */

-- single line comment

Asp.Net markup (aspx): <%-- comment --%>

 

Now here's a neat trick regarding commenting and uncommenting code in Visual Studio and Visual Web Developer. In any code editor, highlighting a bit of code (be it VB.Net, C# or aspx markup), if you press ctrl+(k, c) [That is, press k and then c while holding down control), it'll automagically comment out that part using the comments that apply to the selected code (so, // in C# and ‘ in VB.Net etc). To uncomment, highlight and hit ctrl+(k,u). One thing to keep note is that the uncomment will work if you select any part of the beginning of a line for VB.Net and C#. For aspx markup though, you must select from <% to the closing %> for the ctrl+(k,u) uncommenting to work.

Also, asp.net <%-- --%> comments work server side. So, nothing in them are visible to the compiler. HTML comments work client side. So, if you put anything inside <!-- -->, it'll be visible to the compiler. Hence, if you're trying to comment out some part of markup that fails to compile, you must use the server side <%-- --%> comments.

 

One last trick for today is the auto formatting of code. In a code editor in Visual Studio or Visual Web Developer, you can select some code and hit ctrl+(k,f). This'll auto format that part of the code. This is immensely helpful for formatting aspx markup really quickly. Keep in ind though, that your code must be valid and error-free. If the ctrl+(k,f) trick doesn't work, it's a sign that there's a problem with code/markup.

Hope that helps.

Share or Bookmark this post…
  • Facebook
  • DotNetKicks
  • Digg
  • LinkedIn
  • Technorati
  • del.icio.us
  • Google
  • Live
  • Tumblr
  • msdn Social
  • Ping.fm
  • Reddit
  • Slashdot
  • StumbleUpon
  • TwitThis
Categories: ASP.NET

Memorystream Not Expandable: Invalid Operation Exception

by ashic 24. August 2008 14:31

There's a little gotcha with the MemoryStream class that I just found out. It has 7 constructors. The default constructor has the stream set as expandable, with an initial capacity of 0. The ctors that take the capacity set the capacity to the param, but also keeps the stream expandable. If, however, you use a ctor with the byte[] param, it initializes the stream with the contents of the buffer, but the stream becomes non-expandable.

So, if you have something like this:

byte[] buffer = File.ReadAllBytes("filaname.docx");
MemoryStream ms = new MemoryStream(buffer);
MemoryStream ms2 = new MemoryStream();
ms2.Write(buffer, 0, buffer.Length);

then, ms will NOT be expandable, ms2 will be. So, if you are modifying the stream and the size may increase, the first ctor will not work, but the second approach will work just fine.

 

Hope that helps :)

Share or Bookmark this post…
  • Facebook
  • DotNetKicks
  • Digg
  • LinkedIn
  • Technorati
  • del.icio.us
  • Google
  • Live
  • Tumblr
  • msdn Social
  • Ping.fm
  • Reddit
  • Slashdot
  • StumbleUpon
  • TwitThis
Categories: .NET | ASP.NET

Powered by BlogEngine.NET 1.6.1.0
Theme by Ashic Mahtab

Need an expert?

Ashic Mahtab
ashic@live.com
(+44) 07879927393

Stats

Featured Ads

 

Donations

I maintain this site and create all content entirely in my own time just to help you guys out. If you find the stuff helpful, or cool or just like what you see, I'd appreciate you chipping in to help out with the hosting costs. It's easy to do so - just click the button below - no amount is too low :)