4

リフレクションを使用して動的クラスからフィールドまたはプロパティを取得しようとしていますが、Getfield または GetProperty を使用して動的オブジェクトを呼び出すと、フィールドが見つからず、動的 object.Try* メソッドが入力されません。

これが .net4 で機能しない理由がわかりません。

testdyn 動的テスト クラスについては、以下を参照してください。

私はこのように呼んでいます:

        dynamic td = new testdyn();
        td.SendDebugEvent += new DebugDelegate(debug);
        td.test();

これらの結果を得る:

one = -1 
two = -1 
fiddle = -1 
test = -1 
set: fiddle = 241827974 
fiddle = -1

見ることを期待する

one = 1
two = 2
fiddle = 3
test = -1
set: fiddle = 241827974
fiddle = 241827974

私は何を間違っていますか?

注:「td.fiddle」を呼び出すと機能します...しかし、クラスを作成するための名前がわからないのに、それにアクセスするためには知っているのは奇妙に思えます??

this post から、idynamicmetaobjectprovider を実装しているため、dynamicobject ではおそらくリフレクションがサポートされていないようです。

動的オブジェクトのメンバーを反映​​するにはどうすればよいですか?

問題は、このコードがリフレクションを使用する外部アプリによって使用されていることです。

アイデアがあれば教えてください。

コードは続きます。

   public delegate void DebugDelegate(string msg);
 public class testdyn : System.Dynamic.DynamicObject
    {
        List<string> items = new List<string>(new string[] { "one", "two", "fiddle", "my", "lou" });
        List<int> vals = new List<int>( new int[] { 1,2,3,5,8 });

        public event DebugDelegate SendDebugEvent;
        void debug(string msg)
        {
            if (SendDebugEvent!=null)
                SendDebugEvent(msg);
        }

        public void set(string name, int v)
        {
            var idx = items.IndexOf(name);
            if (idx < 0)
                return;
            vals[idx] = v;
            debug("set: " + name + " = " + v);
        }

    int get(string name)
    {
        object o = null;
        var t = GetType();
        try {
        o = t.GetProperty(name).GetValue(this, null);
        int v = (int)o;
        return v;
        } catch 
        {
            try
            {
                var f = t.GetField(name);
                o = f.GetValue(this);
                return (int)o;
            }
            catch 
            { 

            }
        }
        return -1;
    }

        string g(string name) { return name+" = "+get(name).ToString(); }
        Random r = new Random();
        public void test() { test(string.Empty); }
        public void test(string mytmp)
        {
            var t = GetType();
            // do some reads
            debug(g("one"));
            debug(g("two"));
            debug(g("fiddle"));
            debug(g("test"));
            // do some sets
            set("fiddle", r.Next());
            // they should change
            debug(g("fiddle"));
        }

        public override bool TryInvokeMember(System.Dynamic.InvokeMemberBinder binder, object[] args, out object result)
        {
            debug("got invoke member");
            return base.TryInvokeMember(binder, args, out result);
        }

        public override bool TrySetMember(System.Dynamic.SetMemberBinder binder, object value)
        {
            debug("got setmember");
            return base.TrySetMember(binder, value);
        }

        public override bool TryGetIndex(System.Dynamic.GetIndexBinder binder, object[] indexes, out object result)
        {
            debug("got getindex");
            return base.TryGetIndex(binder, indexes, out result);
        }

        public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result)
        {
            // get index of column value trying to be retrieved
            var idx = items.IndexOf(binder.Name);
            // default to empty
            result = string.Empty;
            // return error if we can't find
            if (idx < 0)
            {
                return base.TryGetMember(binder, out result);
            }
            // get result
            result = vals[idx];
            return true;
        }

        public override bool TryInvoke(System.Dynamic.InvokeBinder binder, object[] args, out object result)
        {
            debug("got invoke");
            return base.TryInvoke(binder, args, out result);
        }



        public override bool TryCreateInstance(System.Dynamic.CreateInstanceBinder binder, object[] args, out object result)
        {
            debug("got create instance");
            return base.TryCreateInstance(binder, args, out result);
        }

        public override IEnumerable<string> GetDynamicMemberNames()
        {
            debug("got member names");
            return items.ToArray();
        }
    }
4

1 に答える 1

1

リフレクションは動的プロパティでは機能しません (ただし、ICustomTypeProviderを実装すると、.net4.5 例外が発生する可能性があります) 。

ImpromptuInterface (nuget で入手可能) と呼ばれるオープン ソースの DLR スイス アーミー ナイフ フレームワークを作成しました。その中には、リフレクションを使用してプロパティに動的にアクセスする外部コードの正確な理由から、動的プロパティをブリッジするように設計された静的メソッドがあります。Impromptu.ActLikeProperties(this object originalDynamic, IDictionary<string, Type>propertySpec) ActLikeProperties

問題は、プロパティ名と戻り値の型の辞書をメソッドに提供し、結果を外部 API に渡す必要があることです。私のメソッドDynamicObjectは、dlr を使用して記述したプロパティ呼び出しを転送する発行されたプロキシでラップすることによって機能します。静的定義から動的型への辞書で。

td.ActLikeProperties(new Dictionary<string,type>{{"one":typeof(int)},{"two":typeof(int) },{"fiddle":typeof(int) },{"test":typeof(int) }});
于 2012-12-20T17:39:29.897 に答える