2012-06-22 19 views
5

私は現在、戻り値タイプboolのDLLを呼び出すために使用されているメソッドを持っています。この方法は、私があらゆるタイプのDLLからの戻り値を取得できるように、私はこの方法を拡張したい、今すぐ一般的なメソッドの定義

public static bool InvokeDLL(string strDllName, string strNameSpace, 
          string strClassName, string strMethodName, 
          ref object[] parameters, 
          ref string strInformation, 
          bool bWarnings = false) 
{ 
    try 
    { 
     // Check if user has access to requested .dll. 
     if (!File.Exists(Path.GetFullPath(strDllName))) 
     { 
      strInformation = String.Format("Cannot locate file '{0}'!", 
              Path.GetFullPath(strDllName)); 
      return false; 
     } 
     else 
     { 
      // Execute the method from the requested .dll using reflection. 
      Assembly DLL = Assembly.LoadFrom(Path.GetFullPath(strDllName)); 
      Type classType = DLL.GetType(String.Format("{0}.{1}", 
             strNameSpace, strClassName)); 
      if (classType != null) 
      { 
       object classInstance = Activator.CreateInstance(classType); 
       MethodInfo methodInfo = classType.GetMethod(strMethodName); 
       if (methodInfo != null) 
       { 
        object result = null; 
        result = methodInfo.Invoke(classInstance, new object[] { parameters }); 
        return Convert.ToBoolean(result); 
       } 
      } 

      // Invocation failed fatally. 
      strInformation = String.Format("Could not invoke the requested DLL '{0}'! " + 
              "Please insure that you have specified the namespace, class name " + 
              "method and respective parameters correctly!", 
              Path.GetFullPath(strDllName)); 
      return false; 

     } 
    } 
    catch (Exception eX) 
    { 
     strInformation = String.Format("DLL Error: {0}!", eX.Message); 
     if (bWarnings) 
      Utils.ErrMsg(eX.Message); 
     return false; 
    } 
} 

です。私はジェネリックスを使ってこれを行うことを計画しましたが、すぐに私には分かりませんでした。コンパイル時に未知のTを返すにはどうすればいいですか?私はリフレクションを見ましたが、この場合にどのように使用されるのかは分かりません。上記のコードで

public static T InvokeDLL<T>(string strDllName, string strNameSpace, 
          string strClassName, string strMethodName, 
          ref object[] parameters, ref string strInformation, 
          bool bWarnings = false) 
{ 
    try 
    { 
     // Check if user has access to requested .dll. 
     if (!File.Exists(Path.GetFullPath(strDllName))) 
     { 
      strInformation = String.Format("Cannot locate file '{0}'!", 
              Path.GetFullPath(strDllName)); 
      return "WHAT/HOW??"; 
     ... 

を最初にチェックしてくださいどのように私は私が望むものを達成することができ、または私はちょうどメソッドをオーバーロードしなければなりませんか?

ご協力いただきありがとうございます。

+3

2番目のコードブロックでは、エラー状態のように見えます。 '新しいArgumentException()をスローする方が適切なのでしょうか?他のリターンについては、Heinziが示唆していることをしてください。 –

+0

+1この場合はわかりません。 Exception.Messageが時にはユーザーの目に見えないことがあるため、エラーの原因を自分で定義することがより明確になることがあります。しかし、私はこれがそのようなケースの1つであるとは確信していません。あなたの時間をありがとう... – MoonKnight

+2

私はジェシーと同意します - あなたが見つけたり、メソッドを呼び出すことに失敗した場合は、スローする必要があります。ユーザーは、収益が成功を意味すると予想する必要があります。管理された世界は、このような失敗を伝えるために例外を使います。特別なリターンではありません。 – payo

答えて

6

return (T)result; 
+0

本当にありがとうございます。各タイプのデフォルト値がどこにあるかを知ることができますか?それはMSDNや言語ガイドにはないようですか? – MoonKnight

+1

@Killercam [Here](http://msdn.microsoft.com/en-us/library/83fhsxwc(v = vs.100).aspx)では、参照型は常に「null」です。 –

+0

@AdamHouldsworth大変ありがとうございます。大変感謝しています。 – MoonKnight

4

場合によって

return false; 

return default(T); 

return Convert.ToBoolean(result); 

によって置き換えDLLから実際の価値が得られていない場合は、明らかにどこかの値を作成する必要があります。可能なすべてのタイプTに対応する唯一の方法は、そのタイプのデフォルト値が何であれ、return default(T)です(つまり、0intnullはすべての参照タイプ)。

typeパラメータに型制約を配置すると、より多くのオプションを得ることができますが、汎用性は犠牲になります。

2

私はこのようなものだろう:

public static InvokeDLLResult<T> InvokeDLL<T>(string strDllName, string strNameSpace, 
         string strClassName, string strMethodName, 
         ref object[] parameters, 
         ref string strInformation, 
         bool bWarnings = false) 
    { 
     try 
     { 
      // Check if user has access to requested .dll. 
      if (!File.Exists(Path.GetFullPath(strDllName))) 
      { 
       strInformation = String.Format("Cannot locate file '{0}'!", 
                 Path.GetFullPath(strDllName)); 
       return InvokeDLLResult<T>.Failure; 
      } 
      else 
      { 
       // Execute the method from the requested .dll using reflection. 
       Assembly DLL = Assembly.LoadFrom(Path.GetFullPath(strDllName)); 
       Type classType = DLL.GetType(String.Format("{0}.{1}", strNameSpace, strClassName)); 
       if (classType != null) 
       { 
        object classInstance = Activator.CreateInstance(classType); 
        MethodInfo methodInfo = classType.GetMethod(strMethodName); 
        if (methodInfo != null) 
        { 
         object result = null; 
         result = methodInfo.Invoke(classInstance, new object[] { parameters }); 
         return new InvokeDLLResult<T>(true, (T) Convert.ChangeType(result, methodInfo.ReturnType)); 
        } 
       } 

       // Invocation failed fatally. 
       strInformation = String.Format("Could not invoke the requested DLL '{0}'! " + 
                 "Please insure that you have specified the namespace, class name " + 
                 "method and respective parameters correctly!", 
                 Path.GetFullPath(strDllName)); 
       return InvokeDLLResult<T>.Failure; 

      } 
     } 
     catch (Exception eX) 
     { 
      strInformation = String.Format("DLL Error: {0}!", eX.Message); 
      if (bWarnings) 
       Debug.WriteLine(eX.Message); 
      return InvokeDLLResult<T>.Failure; 
     } 
    } 

    public class InvokeDLLResult<T> 
    { 
     public InvokeDLLResult(bool success, T result) 
     { 
      Success = success; 
      Result = result; 
     } 

     public bool Success { get; private set; } 
     public T Result { get; private set; } 

     public static InvokeDLLResult<T> Failure = new InvokeDLLResult<T>(false, default(T)); 
    } 

それとも、私は結果を返すために、出力パラメータを使用して、TryInvokeDLL方法を記述しますが。

+0

私はこれが好きです。乾杯... – MoonKnight

+0

+1、非常にエレガント。私はあなたが 'Convert.ChangeType(result、methodInfo.ReturnType)'をスキップできると思います。 'result'は' methodInfo'で参照されるメソッドから返されているので、すでに 'methodInfo.ReturnType'の動的型を持っていなければなりません。ああ、私は 'strInformation'を返すオブジェクトに追加します:' ref'パラメータは醜いです。 ;-) – Heinzi

+0

あなたは@Heinziの両方のカウントで正解です。 – neontapir

関連する問題