[C#] ParameterInfo vs values

Pagina: 1
Acties:

Onderwerpen


  • robertpNL
  • Registratie: Augustus 2003
  • Niet online
Hallo,

Ik ben een beetje aan het rommelen met Reflection, en dan met name met de methode MethodBase.GetCurrentMethod()

Zie dit stukje code:

code:
1
2
3
4
5
6
7
8
using System.Reflection;

public void Test(string Param)
{
  MethodBase method = MethodBase.GetCurrentMethod();
  foreach (ParameterInfo p in RunningMethod.GetParameters())
  { ... }
}


Het mag duidelijk zijn dat de variable 'method' naar deze methode ('Test') verwijst. En de methode parameters (signature) kan ik uitlezen met de array 'ParameterInfo[]' van 'method'. Niet spannend allemaal.

Nu weet ik dat ik niet de values kan uitlezen die aan de methode worden meegegeven (bijvoorbeeld die van 'Param') via ParameterInfo[]. Want ParameterInfo geeft alleen informatie over de class, en niet over het object.

Toch vraag ik mij af of ik via een truuk kan weten welke waardes worden meegegeven aan deze method. Dus op een dynamische manier achter kan komen welke parameters aan deze method zijn meeggeven en wat de waardes daarvan zijn.

Iemand?

PS Iemand die zich afvraagt waarom ik dit wil, het is uiteindelijk bedoeld voor de trace class om informatie omtrent aanroepende methodes aan zijn listeners door te geven.

  • whoami
  • Registratie: December 2000
  • Laatst online: 18:57
Hmm, ik weet niet of het lukt, maar ParameterInfo heeft een Member property die van het type MemberInfo is.
Als je dan die MemberInfo cast naar een FieldInfo bv (als het een FieldInfo is; FieldInfo erft over van MemberInfo), dan zou je de waarde van dat Field kunnen hebben....
Echter, ik vrees dat dit niet zal lukken; een parameter is nl. geen field, maar je kan het proberen.

https://fgheysels.github.io/


  • eek
  • Registratie: Februari 2001
  • Laatst online: 06-04-2020

eek

@MagickNET

http://channel9.msdn.com/ShowPost.aspx?PostID=227924

Hier staat een heel verhaal en uitleg waarom het niet direct mogelijk is. Als iemand een andere truck weet dan in het verhaal staat dan hoor ik het graag. Ik zou graag ook bij het optreden van een exceptie de inhoud van mijn locale variabelen zien, maar als ik het verhaal goed begrijp is dat stackframe dan al weg.

Skill is when luck becomes a habit.


  • robertpNL
  • Registratie: Augustus 2003
  • Niet online
eek schreef op woensdag 27 september 2006 @ 17:25:
http://channel9.msdn.com/ShowPost.aspx?PostID=227924

Hier staat een heel verhaal en uitleg waarom het niet direct mogelijk is. Als iemand een andere truck weet dan in het verhaal staat dan hoor ik het graag. Ik zou graag ook bij het optreden van een exceptie de inhoud van mijn locale variabelen zien, maar als ik het verhaal goed begrijp is dat stackframe dan al weg.
Voor het kwijtraken van de stackframe bij een exception zou je dit kunnen oplossen met een FIFO van stackframes. Zie een-na-laatste reactie van je link.

Je moet iedere functie voorzien van een "start"/"end" call naar static methodes van een object. In dat object maak je een collectie waarin je iedere stackframe opslaat. En bij een "end"-functie verwijder je de bovenste stackframe. En bij een exception heb je een collectie van stackframes op dat moment. Let op, voorkom 'return' methode middenin een functie.

Aleen dan heb je nog niet de waardes van variabelen op dat moment. :/

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 18:57
*schopje*
Om hier nog ff op terug te komen...

Met reflection is het idd niet mogelijk om de waardes v/d argumenten van je methods uit te lezen.
Een nadeel om dit logging gedeelte met reflection op te lossen, is ook dat je je methods moet 'vervuilen' met een call naar je 'logging method'.
Aspect Oriented Programming is uiterst geschikt om dit soort problemen op te lossen.

Je zou een 'advice' kunnen maken die het logging gedeelte voor zich neemt, en je kan die 'advice' dan at runtime 'weaven' in je applicatie op de plaatsen waar die moet uitgevoerd worden. (Bv op ieder 'method-entry' punt moet de advice uitgevoerd worden).
Het Spring.NET framework biedt je de mogelijkheden om dit te doen:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MethodInvocationLoggingAdvice : IMethodBeforeAdvice
{

  public void Before( System.Reflection.MethodInfo method, 
    object[] args, object target )
  {
    string message = method.Name + " called with ";

    string arguments = string.Empty;

    for( int i = 0; i < args.Length; i++ )
    {
      arguments += args[i] +", ";
    }

    Console.WriteLine (message + arguments.SubString (0, arguments.Length - 2));
  }
}

^^ Dit is dus een 'advice', en die class bevat enkel de logging-logica. (Zoals je kan zien, kan je op deze manier wel aan de values van de argumenten die gepassed werden.

Het enige wat je dan moet doen, is aangeven dat die 'advice' geweaved moet worden in een class / classes:
code:
1
2
3
4
5
6
7
8
9
10
11
12
static void Main()
{
  ProxyFactory f = new ProxyFactory (new TestClass());

  f.AddAdvice (new MethodInvocationLoggingAdvice());

  ITest t = (ITest)f.GetProxy();

  t.SayHello ("whoami");

  t.Shout ("Watch out");
}

De class 'TestClass' waarin hier eerder naar gerefereerd werd, is de class die de methods bevat waarvan de method-calls moeten gelogged worden. In dit voorbeeld heeft die class dus de methods 'SayHello' en Shout. In die methods zelf, moet je helemaal geen andere logica opnemen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface ITest
{
  void SayHello( string name );
  void Shout( string message );
}

public class TestClass : ITest
{
  public void Method1( string name )
  {
    Console.WriteLine ("Hello " + name + " ! ");
  }

  public void Shout( string message )
  {
    Console.WriteLine (message + "!!!!!!!");
  }
}


Ik heb er ook een postje over geschreven op m'n weblog.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • robertpNL
  • Registratie: Augustus 2003
  • Niet online
@whoami

Bedankt voor je waardevolle informatie. :) Ga ik zeker in verdiepen.

[ Voor 3% gewijzigd door robertpNL op 06-11-2006 10:16 ]

Pagina: 1