2016-06-22 5 views
1

私はリフレクションを学習していますが、保存してからロードしてトリガーできるシリアル化可能なアクションタイプに取り組んでいます。 serializeableアクションは、パラメータを持たないメソッドまたはint、float、double、stringまたはbool型の単一パラメータをサポートします。名前が渡されたのいずれか、彼らはまた、デフォルト値を持つつの属性を持っている可能性が上に挙げた種類のつの属性を持っているか、なしすべての属性を持っている方法のC#のリフレクションを使用した単一または無の属性のメソッドを取得する

すべて。 ここに私の問題が来る。まず、オーバーロードを持つメソッドに対してtarget.GetType().GetMethod(methodName);を呼び出すと、AmbiguousMatchExceptionが発生し、オプションの単一のパラメータでメソッドを呼び出すとNULLが返されます。

私が今行っているのは、AmbiguousMatchExceptionをキャッチするtry-catchから始まり、指定されたメソッドにオーバーロードがあることがわかります。

public static MethodInfo GetMethod(string methodName, Object _target) 
    { 
     try 
     { 
      MethodInfo info = _target.GetType().GetMethod(methodName); 
      return info; 
     } 
     catch (AmbiguousMatchException ex) 
     { 
      MethodInfo info = _target.GetType().GetMethod(methodName, new System.Type[0]); 
      if (info != null) return info; 
      info = _target.GetType().GetMethod(methodName, new[] { typeof(int) }); 
      if (info != null) return info; 
      info = _target.GetType().GetMethod(methodName, new[] { typeof(float) }); 
      if (info != null) return info; 
      info = _target.GetType().GetMethod(methodName, new[] { typeof(double) }); 
      if (info != null) return info; 
      info = _target.GetType().GetMethod(methodName, new[] { typeof(string) }); 
      if (info != null) return info; 
      info = _target.GetType().GetMethod(methodName, new[] { typeof(bool) }); 
      return info; 
     } 
    } 

これは非常に醜いですが、それはオーバーロードされたメソッドのためにいい作品:私は例外を取得した場合、私はを検索するためのさまざまな属性タイプの方法通過アレイを取得しようとし始めます。ただし、メソッドにオプションのパラメータがある場合はNULLを返します。 OptionalParamBindingバインディングフラグを使用しようとしましたが、オーバーロードされていないメソッドとオプションの単一のパラメータに対してもNULLを返しました。

私の質問は次のとおりです: どうすればいいですか? - int、float、double、stringまたはboolパラメータを持つメソッドのオーバーロード - それが失敗した場合は、オプションのint、float、double、stringまたはboolパラメータによるオーバーロード - それが失敗した場合は、パラメータなしのオーバーロード

+2

代わりに 'GetMethods'を使用して、一致するものが見つかるまでループすることができます。個人的には、特定の方法が必要な場合は、正しい方法を見つけるのに役立つと期待されているパラメータの種類を求めています。 – TyCobb

答えて

3

特定の要件については、LINQクエリでこれを行うのはかなり簡単です。

var validParameterTypes = new HashSet<Type> { typeof(int), typeof(float), ... }; 

var methods = from method in _target.GetType().GetMethods() 
       let parameters = method.GetParameters() 
       let hasParameters = parameters.Length > 0 
       let firstParameter = hasParameters ? parameters[0] : null 
       let isOptionalParameter = (hasParameters && firstParameter.IsOptional) ? true : false 
       where method.Name == methodName && 
        (!hasParameters || validParameterTypes.Contains(firstParameter.ParameterType)) 
       orderby parameters.Length descending, isOptionalParameter 
       select method; 

どの時点でメソッドがクエリから出てくるかを評価し、ニーズに合っているかどうかを確認します。

しかし、別の質問があります。「になりますか?」という疑問があります。 TyCobbはすでに彼のコメントでこれを言及しており、彼は正しい。

あなたがやろうとしている現在の方法は、すぐに利益を上げるための多くの仕事です。だからあなたは過負荷のリストを得て、それは本当にあなたを助けません。今度は、自分自身でオーバーロードの解決をしなければなりませんし、呼び出すための「最良の」オーバーロードを見つけなければなりません(または、最初に見つけたものを取るが、メソッドが追加/削除/変更された場合、

あなたが探しているパラメータタイプ(ある場合)も格納しているとします。これを知ることで、あなたのコードは以下のように縮約されます:

var parameterTypes = (knownParameterType == null) ? Type.EmptyTypes : new[] { knownParameterType }; 
var method = _target.GetType().GetMethod(methodName, parameterTypes); 

もっと簡単で、よりクリーンで、より明らかに正しい!許可されたパラメータ型をここで確認する必要もなく、定義している有効な「アクション型」を構築する際にそれを行うようにしてください。

関連する問題