Why does C # dynamics allow internal properties but not methods?

I have a library with the following classes:

public interface IEntity { string Foo { get; } void Bar(int x); } public class EntityFactory { public static IEntity createEntity() { return new Entity(); } } internal class Entity : DynamicObject, IEntity { public void Bar(int x) { Console.WriteLine("inside Bar"); Console.WriteLine("bar {0}", x); } public string Foo { get { Console.WriteLine("inside Foo getter"); return "foo"; } } public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { Console.WriteLine("inside TryInvokeMember(binder.Name = '{0}')", binder.Name); return base.TryInvokeMember(binder, args, out result); } public override bool TryGetMember(GetMemberBinder binder, out object result) { Console.WriteLine("inside TryGetMember(binder.Name = '{0}')", binder.Name); if (binder.Name == "SomeVar") { result = 42; return true; } return base.TryGetMember(binder, out result); } } 

and the program that uses them:

 public static void Main(string[] args) { dynamic entity = EntityFactory.createEntity(); Console.WriteLine("entity.Foo = {0}", entity.Foo); entity.Bar(24); Console.WriteLine("entity.SomeVar = {0}", entity.SomeVar); } 

Output signal

 inside Foo getter entity.Foo = foo inside TryInvokeMember(binder.Name = 'Bar') inside TryGetMember(binder.Name = 'Bar') 

and then I get an exception

 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: `EntityLib.Entity.Bar(int)' is inaccessible due to its protection level 

Why does a dynamic object directly refer to the Foo property, but does not call the Bar method and uses TryInvokeMember and TryGetMember ? They have the same access modifiers.

Update: The described behavior is observed in Mono. Microsoft does not work already when accessing the Foo property. The following code works as intended:

 public static void Main(string[] args) { var entity = EntityFactory.createEntity(); entity.Bar(24); Console.WriteLine("entity.Foo = {0}", entity.Foo); dynamic e = entity; Console.WriteLine("entity.SomeVar = {0}", e.SomeVar); } 

Whether this will be a bug or any function should be decided by Microsoft. However, I expect the conversion of the variable to dynamic should not restrict access.

+6
source share
1 answer
  internal class Entity .... 

A dynamic keyword is not a workaround for limited availability. The Entity class is declared internal, therefore, trying to call its Bar () method from code that is not part of the assembly in which Entity lives, will be rejected by the binder, the message leaves little in mind:

EntityLib.Entity.Bar (int) 'is unavailable due to protection level

The logical way to promote is to declare an Entity public class. If for some reason this is a problem, you can break the rules with Reflection. You need to use BindingFlags.NonPublic | BindingFlag.Instance parameters in a call to Type.GetMethod ().

Regarding the main issue, I will gladly refuse this as a mistake. Middleware C # DLR cannot be redesigned. Not least because the code for it is not included in the reference source, Microsoft seems to regard it as a trade secret. It. You can specify it at connect.microsoft.com

+7
source

Source: https://habr.com/ru/post/953708/


All Articles