Intercept get method call in c #

Let's assume we have this class:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

      

Now, is it possible in C # to intercept a call to the getter of a property, run another method, and return the result of that method instead of the value of the property? I would like to be able to do some additional logic behind the scenes. The disadvantage is that this class cannot be changed (at the C # level). Maybe some kind of IL?

+2


a source to share


9 replies


The .NET SDK has what you need. You can get around anything on the CLR by disassembling / rebuilding (ildasm.exe and ilasm.exe) if you're careful. Be sure to run the Visual Studio Command Prompt to have these tools in your PATH.

1) ildasm person.exe

2) File -> Dump (person.il)



3) Edit and modify the get_Name () method: IMPORTANT: when modifying a method at the IL level, always recalculate the .maxstack, as the Visual Studio .NET compilers will set it exactly for most methods, if you add any code, raise the .maxstack. to handle the maximum # of values โ€‹โ€‹per runtime stack for this method, unless you get an invalid program.

  .method public hidebysig specialname instance string get_Name() cil managed
  {
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
    // Code size       11 (0xb)
    .maxstack  2
    .locals init (string V_0)
    IL_0000:  ldarg.0
    IL_0001:  ldfld      string Person::'<Name>k__BackingField'
    IL_0006:  stloc.0
    IL_0009:  ldloc.0
        IL_000a:  ldstr "IL code inserted here"
        call    void [mscorlib]System.Console::WriteLine(string)
    IL_001a:  ret
 } // end of method Person::get_Name

      

4) Reassemble: ilasm person.il

+1


a source


Take a look at PostSharp: http://www.sharpcrafters.com/

This implements exactly what you are looking for and more.



PostSharp implements aspect-oriented programming for .NET. This is a commercial product. Very cool.

Just remember that any solution to this problem will come with some runtime overhead (some memory, some extra time to make function calls). Nothing is completely free.

+7


a source


If your class cannot be modified , you can look into tools like PostSharp - it allows you to intertwine code that intercepts or replaces method and property calls.

If you can change the code , just avoid using the automatic property and do get and set operations explicitly. Then you can do whatever you need to do. Alternatively, you can define the property as virtual and get another class to change the behavior of the getter and / or setter:

public class Person 
{ 
  public virtual int Id { get; set; } 
  public virtual string Name { get; set; } 
} 

public class PersonDerived : Person
{
  public override int Id { get { ... } set { ... } }
  public override string Name { get { ... } set { ... } }
}

      

If you only need this for unit testing , you might want to look at mocking tools like Moq or TypeMock .

+6


a source


Extend the class and do

public class MyPerson : Person
{
    public new int Id 
    { 
        get
        {
            foo();
            return base.Id;
        }
}

      

+1


a source


Not auto-properties, no.

But you could do:

public class Person
{
    private int _id;

    public int Id
    {
        get
        {
            // Do some logic or call a method here
            return _id;
        }
        set
        {
            if(value <= 0)
                throw new CustomInvalidValueException();

            _id = value;
        }
    }
}

      

0


a source


public Class Person
{
    private int _id;
    public int ID
    {
      get{ MyMethod(); return _id; }
      set{ _id = value; }
    }
   // etc. etc. .....

 }

      

0


a source


private bool _pp;
public bool Propery
{
  get {// your code}
  set {_pp = value; }
}
0


a source


I think you are looking for Aspect Oriented Framework .

0


a source


If you cannot change the class itself, you can use an extension method to get the name. This will change the way the data is accessed, so it might not be an option either. Here's how you would do it, if you're interested:

public static class PersonExtensions
{
    public static string GetName(this Person p)
    {
        foo();
        return p.Name;
    }
}

      

Then you would access the title like this:

Person myPerson = new Person();
string name = myPerson.GetName();  // Also calls foo() for you extra processing

      

Hope it helps.

0


a source







All Articles