When dynamic encounters internal

Source: Internet
Author: User

Dynamic Introduction
. Net 4 introduces dynamic, we can simply and dynamically access the attributes of the object or call its method, avoiding the tedious and indecent reflection:

1 dynamic person = new Person {ID = 1, Name = "Crane chongtian "};
2 var name = person. Name;
3 person. Work ();

Dynamic has restrictions on access to members and only allows access to public members. When you access a private or protected member, an exception is thrown:

This is consistent with other parts of. net.

Dynamic does not support the internal type in other assembly
However, dynamic does not support the internal class in other assembly, but it is a pity.

There are two projects in the solution:

ClassLibrary1 is a class library with two classes:

1
2
3
4
5 internal class Student
{
Public int ID {get; set ;}
Public string Name {get; set ;}
}

1
2
3
4
5
6
7
8
9
10
11 public class StudentRepository
{
Public dynamic GetByID (int id)
{
Return new Student {ID = id, Name = "He chongtian "};
}
Public dynamic Select ()
{
Return new {ID = 2, Name = ""};
}
}

Student is of the internal type.

The WhenDynamicMeetInternal project references ClassLibrary1 and the code in Program is as follows:

1
2
3 var repository = new StudentRepository ();
Dynamic student = repository. GetByID (1 );
Var name = student. Name;

The following exception is thrown during debugging:

I think everyone has thought about it. Why not set Student to public?

Yes. After Students is set to public, the problem can be easily solved:

But it only solves some of the problems, but does not solve the problem. Let's look at the second call:

1
2 dynamic student2 = repository. Select ();
Var name2 = student2.Name;

There are still similar exceptions during debugging:

Why?

From the Watch window, we can see that the type of the anonymous student2 is not public, so it can only be internal (without private classes or structures ). In fact, the anonymous type is internal. If you are not sure, try it yourself.

We can set Student to public, but we can't do anything about the anonymous type.

Dynamic Denial of Service for the internal type of external Assembly brings a lot of trouble. Next we will discuss the solution.

Solution
Use InternalsVisibleTo


Add a line of code to the end of the AssemblyInfo. cs file (SEE) of the ClassLibrary1 project:

1 [assembly: InternalsVisibleTo ("WhenDynamicMeetInternal")]

This method has many disadvantages and is not recommended.

Create a new dynamic ReflectionDynamicObject
Create a ReflectionDynamicObject class, inherit to DynamicObject, override TryGetMember, TryInvokeMember, and other methods, the Code is as follows:

1 using System. Dynamic;
2 using System. Globalization;
3 using System. Reflection;

4

5 internal sealed class ReflectionDynamicObject: DynamicObject
6 {
7 private object RealObject {get; set ;}

8

9 public override bool TryConvert (ConvertBinder binder, out object result)
10 {
11 result = this. RealObject;

12 return true;
13}
14 public override bool TryGetMember (GetMemberBinder binder, out object result)
15 {
16 PropertyInfo property = this. RealObject. GetType (). GetProperty (binder. Name, BindingFlags. GetProperty |
17 BindingFlags. Public | BindingFlags. Instance );
18 if (property = null)
19 {
20 result = null;
21}
22 else
23 {
24 result = property. GetValue (this. RealObject, null );
25 result = WrapObjectIfInternal (result );
26}

27 return true;
28}
29 public override bool TryInvokeMember (InvokeMemberBinder binder, object [] args, out object result)
30 {
31 result = this. RealObject. GetType (). InvokeMember (binder. Name, BindingFlags. InvokeMethod |

32 BindingFlags. NonPublic |
33 BindingFlags. Public | BindingFlags. Instance, null, this. RealObject, args, CultureInfo. InvariantCulture );
34 return true;
35}
36 public static object WrapObjectIfInternal (object o)
37 {
38 if (o = null) return null;

39 if (o. GetType (). IsPublic) return o;
40 return new ReflectionDynamicObject {RealObject = o };
41}
42 public override string ToString ()
43 {

44 return this. RealObject. ToString ();
45}
46}

With this class, you can solve the internal problem:

1 dynamic student3 = ReflectionDynamicObject. WrapObjectIfInternal (repository. Select ());
2 v

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.