10

現在、次のようなコードがあります。

Private Sub ShowReport(ByVal reportName As String)
    Select Case reportName
        Case "Security"
            Me.ShowSecurityReport()
        Case "Configuration"
            Me.ShowConfigurationReport()
        Case "RoleUsers"
            Me.ShowRoleUsersReport()
        Case Else
            pnlMessage.Visible = True
            litMessage.Text = "The report name """ + reportName + """ is invalid."
    End Select
End Sub

メソッドの命名規則を使用して物事を単純化するコードを作成する方法はありますか?これが私が探しているものを説明するいくつかの擬似コードです:

Private Sub ShowReport(ByVal reportName As String)
    Try
        Call("Show" + reportName + "Report")
    Catch ex As Exception
        'method not found
    End Try
End Sub
4

12 に答える 12

18
Type type = GetType();
MethodInfo method = type.GetMethod("Show"+reportName+"Report");
if (method != null)
{
    method.Invoke(this, null);
}

これはC#であり、VBに変換するのに十分簡単なはずです。メソッドにパラメーターを渡す必要がある場合は、Invokeの2番目の引数にパラメーターを追加できます。

于 2008-09-25T16:08:28.627 に答える
5

あなたはもっと深い問題を抱えています。あなたの弦はあまりにも重要です。誰があなたにひもを渡しているのですか? そうしないようにすることはできますか?

内部実装 (メソッド名) を外部ビューから分離するため、switch ステートメントを使用してください。

これをドイツ語にローカライズするとします。これらすべてのメソッドの名前を変更しますか?

于 2008-09-25T16:56:39.057 に答える
3

リフレクションを使用してこれを行うこともできますが、正直なところ、同じクラスのコードとswitch()などの特定のシナリオでは複雑すぎると思います。

これで、各レポートタイプを独自のアセンブリ(アドイン/プラグインアーキテクチャのようなもの)に含めるか、単一の外部アセンブリにバンドルするようにアプリを設計した場合は、レポートアセンブリをアプリドメインにロードしてからリフレクションを使用して、このようなことを行います。

于 2008-09-25T16:06:19.847 に答える
3

反射を使用します。System.Reflection名前空間では、メソッドを含む型をMethodInfo使用して、必要なメソッドのオブジェクトを取得する必要があります。GetMethod("methodName")

オブジェクトを取得したら、オブジェクトインスタンスと任意のパラメータを使用してMethodInfo呼び出すことができます。.Invoke()

例えば:

System.Reflection.MethodInfo method = this.GetType().GetMethod("foo");
method.Invoke(this, null);
于 2008-09-25T16:08:17.283 に答える
3

Reflection APIを使用すると、メソッドからを取得し、メソッドを動的にMethodInfo呼び出すことができます。Invokeしかし、あなたの場合はやり過ぎです。

文字列で索引付けされたデリゲートの辞書を作成することを検討する必要があります。

于 2008-09-25T16:10:07.640 に答える
2

リフレクションを使用できます。個人的には、switchステートメントに固執する必要があると思います。

private void ShowReport(string methodName)
{
    Type type = this.GetType();
    MethodInfo method = type.GetMethod("Show"+methodName+"Report", BindingFlags.Public)
    method.Invoke(this, null);
}

申し訳ありませんが、C#を実行しています。VB.NETに変換するだけです。

于 2008-09-25T16:10:23.240 に答える
0

質問を正しく理解している場合は、Reflectionを使用してメソッド "show" + reportNameを見つけ、間接的に呼び出す必要があります。

中途半端な例:

Case "financial" :
{
   Assembly asm = Assembly.GetExecutingAssembly ();

    MethodInfo mi = asm.GetType ("thisClassType").GetMethod ("showFinancialReport");

   if (mi != null)
      mi.Invoke (null, new object[] {});

}

そこに独自のロジックを挿入して、呼び出すメソッドの名前を作成します。

詳細については、MethodInfoとAssemblyのMSDNドキュメントを参照してください。

于 2008-09-25T16:14:37.550 に答える
0

リフレクションの使用:

Type t = this.GetType();
try 
{
    MethodInfo mi = t.GetMethod(methodName, ...);

    if (mi != null)
    {
        mi.Invoke(this, parameters);
    }
} 

しかし、私は前に同意します、あなたの元のコードを変更しない方が良いです;-)

于 2008-09-25T16:15:02.917 に答える
0

System.Reflectionを使用してできます。詳細については、このコードプロジェクトの記事を参照してください。

string ModuleName = "TestAssembly.dll";
string TypeName = "TestClass";
string MethodName = "TestMethod";

Assembly myAssembly = Assembly.LoadFrom(ModuleName);

BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public | 
  BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);

Module [] myModules = myAssembly.GetModules();
foreach (Module Mo in myModules) 
{
 if (Mo.Name == ModuleName) 
     {
     Type[] myTypes = Mo.GetTypes();
     foreach (Type Ty in myTypes)
         {
        if (Ty.Name == TypeName) 
            {
            MethodInfo[] myMethodInfo = Ty.GetMethods(flags);
            foreach(MethodInfo Mi in myMethodInfo)
                {
                if (Mi.Name == MethodName) 
                    {
                    Object obj = Activator.CreateInstance(Ty);
                    Object response = Mi.Invoke(obj, null);
                    }
                }
            }
        }
    }
}
于 2008-09-25T16:07:31.640 に答える
0

Python(およびIronPython)は、このことを非常に簡単に行うことができます。ただし、.Netでは、リフレクションを使用する必要があります。

C#の場合:http://www.dotnetspider.com/resources/4634-Invoke-me-ods-dynamically-using-reflection.aspx

VB.Netへのクイックポート:

Private Sub InvokeMethod(instance as object, methodName as string )
            'Getting the method information using the method info class
            Dim mi as MethodInfo = instance.GetType().GetMethod(methodName)

            'invoing the method
            'null- no parameter for the function [or] we can pass the array of parameters
            mi.Invoke(instance, Nothing)
End Sub
于 2008-09-25T16:10:08.777 に答える
0

「あなたの質問に最も近い」ソリューション。

これらのレポートからデリゲートを作成し、ハッシュテーブルで一致する文字列を検索してそれらを呼び出すことができます。

Public Sub New()
    '...
    ReportTable.Add("Security", New ReportDelegate(AddressOf ShowSecurityReport))
    ReportTable.Add("Config", New ReportDelegate(AddressOf ShowConfigReport))
    ReportTable.Add("RoleUsers", New ReportDelegate(AddressOf ShowRoleUsersReport))
    '...
End Sub

Private Sub ShowSecurityReport()
    '...
End Sub

Private Sub ShowConfigReport()
    '...
End Sub

Private Sub ShowRoleUsersReport()
    '...
End Sub

Private Delegate Sub ReportDelegate()

Private ReportTable As New Dictionary(Of String, ReportDelegate)

Private Sub ShowReport(ByVal reportName As String)
    Dim ReportToRun As ReportDelegate
    If ReportTable.TryGetValue(reportName, ReportToRun) Then
        ReportToRun()
    Else
        pnlMessage.Visible = True
        litMessage.Text = "The report name """ + reportName + """ is invalid."
    End If
End Sub

そうすれば、必要な数のレポートを追加でき、それらを反映する能力、および反映のパフォーマンスヒットは問題になりません。

于 2008-09-25T18:07:31.833 に答える