У меня есть библиотека со следующими классами:Почему C# dynamic разрешает внутренние свойства, но не методы?
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);
}
}
и программу, которая использует их:
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);
}
Выход на
inside Foo getter
entity.Foo = foo
inside TryInvokeMember(binder.Name = 'Bar')
inside TryGetMember(binder.Name = 'Bar')
, а затем я получаю исключение
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: `EntityLib.Entity.Bar(int)' is inaccessible due to its protection level
Почему динамический объект напрямую ссылается на свойство Foo
, но не вызывает метод Bar
и вместо этого использует TryInvokeMember
и TryGetMember
? Они имеют одинаковые модификаторы доступа.
Обновление: Описанное поведение наблюдается на Mono. Microsoft не работает уже при доступе к объекту Foo
. Следующий код работает так, как планировалось:
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);
}
Независимо от того, является ли это ошибкой или функцией, решение должно быть определено корпорацией Майкрософт. Однако я ожидаю, что преобразование переменной в динамическое не должно ограничивать доступ.
Поскольку DynamicObject также имеет TryInvokeMember(), тот, который вы не переопределили, не может быть использован. –
Но я не хочу его переопределять. Я хочу, чтобы 'Bar' выполнялся напрямую. Вот почему я определяю его явно. –
Обновлен вопрос, чтобы сделать его более понятным. –