次のクラスを持つライブラリがあります。
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
and を使用するのはなぜですか? アクセス修飾子は同じです。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);
}
これがバグなのか機能なのかは、Microsoft によって決定されます。ただし、変数を動的に変換してもアクセスが制限されないはずです。