11

Consider this code in a project:

static void Main(string[] args)
{
    DoSomething(new { Name = "Saeed" });
}

public static void DoSomething(dynamic parameters)
{
    Console.WriteLine(parameters.Name);
}

This works like a charm. However, as soon as you separate these two functions into two different projects, the code breaks:

// This code is in a Console Application
static void Main(string[] args)
{
    ExternalClass.DoSomething(new { Name = "Saeed" });
}

// However, this code is in a Class Library; Another project
public class ExternalClass
{

    public static void DoSomething(dynamic parameters)
    {
        Console.WriteLine(parameters.Name);
    }
}

The error I get in the second case is:

object' does not contain a definition for 'Name' (RuntimeBinderException)

Why do I get this error? What's the alternative method? How can I pass a dynamic parameter to a method in another library, and use it there in a simple way?

Note: I'm familiar with ExpandoObject and I don't want to use that.

Saeed Neamati
  • 35,341
  • 41
  • 136
  • 188
  • Search of the above link took 10 seconds of googling, think about it :-) – zerkms Jul 13 '13 at 11:31
  • @zerkms, thanks, how about I wasn't good at C# keywords ;) to google it. – Saeed Neamati Jul 13 '13 at 11:33
  • perhaps :-) my search request was: "C# dynamic different project" PS: I don't develop in c# these days and haven't used `dynamic` either – zerkms Jul 13 '13 at 11:34
  • @zerkms he say:Note: I'm familiar with ExpandoObject and I don't want to use that.so this is not dupplicate –  Jul 13 '13 at 11:36
  • @Shahrooz Jefri ㇱ: oh I see. Was it in the original question? – zerkms Jul 13 '13 at 11:38
  • My _guess_, is that as it's an anonymous type, I'm not _positive_ (will check) but since they're normally bound to a single assembly, I wouldn't be surprised if their properties are defined as `internal {get;}`. `dynamic` leverages reflection to read members and unless you have `InternalsVisibleTo` to your other project, I wouldn't be surprised if it couldn't read that information. EDIT: Try adding the `[InternalsVisibleTo](http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx)` attribute and see if that helps.EDIT:better yet, declare a class. – Chris Sinclair Jul 13 '13 at 11:44

1 Answers1

8

Your code is using an anonymous type. Originally intended to be useful in a Linq select query expression, added in C# version 3. Unfortunately, the C# compiler generates them with the accessibility modifier for the members in the anonymous type set to internal. Accessibility is enforced by the CLR. Not an issue in Linq since the iterator will be generated in the same assembly as well. Using them with the dynamic keyword was not envisioned, it was added in a later C# version, version 4.

Which means that it will work fine as long as the code is all in the same assembly. However, as soon as you pass the object to code in another assembly, the restrictions enforced by internal kick in and it goes kaboom.

Simply declaring a little public class is the workaround. ExpandoObject works too but adds unnecessary overhead.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    I guess it's not a good design. But of course, I'm not familiar with the limitations of C# language and CLR. Thanks for the information. – Saeed Neamati Jul 13 '13 at 12:50