using System;
using System.Dynamic;
using System.Reflection;
namespace MoroMoro.Dynamic
{
public sealed class MemberAdapter : DynamicObject
{
private static BindingFlags GetBindingFlags(bool ignoreCase)
{
var baseFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy;
return (ignoreCase ? (baseFlags | BindingFlags.IgnoreCase) : baseFlags);
}
public MemberAdapter(object target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
this._target = target;
}
private readonly object _target;
private Type TargetType
{
get
{
return this._target.GetType();
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var flags = GetBindingFlags(binder.IgnoreCase);
var field = TargetType.GetField(binder.Name, flags);
var property = TargetType.GetProperty(binder.Name, flags);
if (field != null)
{
result = field.GetValue(this._target);
return true;
}
else if ((property != null) && (property.CanRead))
{
result = property.GetValue(this._target, null);
return true;
}
else
{
result = null;
return false;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
var flags = GetBindingFlags(binder.IgnoreCase);
var field = TargetType.GetField(binder.Name, flags);
var property = TargetType.GetProperty(binder.Name, flags);
if (field != null)
{
field.SetValue(this._target, value);
return true;
}
else if ((property != null) && (property.CanRead))
{
property.SetValue(this._target, value, null);
return true;
}
else
{
return false;
}
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
var flags = GetBindingFlags(binder.IgnoreCase);
var filter = (MemberFilter)((member, c) =>
{
var memberAsMethod = member as MethodInfo;
if (memberAsMethod == null)
{
return false;
}
if (!string.Equals(memberAsMethod.Name, binder.Name, (binder.IgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)))
{
return false;
}
var parameters = memberAsMethod.GetParameters();
if (args.Length != parameters.Length)
{
return false;
}
for (var i = 0; i < parameters.Length; i++)
{
var parameter = parameters[i];
var arg = args[i];
if (arg == null)
{
continue;
}
if (parameter.ParameterType.IsAssignableFrom(arg.GetType()))
{
continue;
}
return false;
}
return true;
});
var methods = TargetType.FindMembers(MemberTypes.Method, flags, filter, null);
if ((methods == null) || (methods.Length == 0))
{
result = null;
return false;
}
var method = (MethodInfo)methods[0];
result = method.Invoke(this._target, args);
return true;
}
}
}
サンプル
class Program
{
class Sample
{
public Sample()
{
this._i = 0;
}
private readonly int _i;
private void Method1()
{
Console.WriteLine(_i);
}
}
static void Main()
{
var s = new Sample();
dynamic m = new MemberAdapter(s);
m._i++;
m.Method1();
Console.ReadKey();
}
}
クラスもらいました~。スマートにかけてて綺麗です
2010.11.08 19:42 URL | kassyi #mQop/nM. [ 編集 ]
ありがとうございます
どうぞ使ってやってください^^
2010.11.08 23:27 URL | よこけん #Ay6tTHf6 [ 編集 ]
いい仕事してますね!
非常に便利です。使わせてもらいますね。
2011.07.06 10:19 URL | ash #mQop/nM. [ 編集 ]
トラックバックURL↓
http://csharper.blog57.fc2.com/tb.php/285-9c00b8b6