问题
Let's assume that 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 call to property get method, run some other method and return result of that method instead of property value? I'd like to be able to do some additional logic behind the scene. The downside is that this class can't be changed (on C# level). Maybe some IL ?
回答1:
The .NET SDK has what you need already. You can round-trip most anything on the CLR by disassembly/reassembly (ildasm.exe and ilasm.exe) if you are careful. Make sure to start a "Visual Studio Command Prompt" so these tools are 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 .maxstack, since the Visual Studio .NET compilers will have set it exactly for most methods, if you add any code, raise .maxstack to handle the maximum # of values on the runtime stack for that method, if not you'll 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) Re-assemble : ilasm person.il
回答2:
Look into PostSharp: http://www.sharpcrafters.com/
This implements exactly what you're looking for, and a whole lot more.
PostSharp implements Aspect Oriented Programming for .NET. Its a commercial product. Very cool.
Just be aware that any solution to this problem will involve some runtime overhead (some memory, some extra time to make function calls.) Nothing is absolutely free.
回答3:
If your class can't be changed, you can look into using tools like PostSharp - it allows you to weave in code that intercepts or replaces calls to methods and properties.
If you can change the code, then just avoid using an automatic property, and implement the get and set operations explicitly. Then you can do whatever you need. Alternatively, you can define the property as virtual and derive another class to change th 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 need this just for unit testing, you may want to look into mocking tools like Moq or TypeMock.
回答4:
Extend the class and do
public class MyPerson : Person
{
public new int Id
{
get
{
foo();
return base.Id;
}
}
回答5:
Not with 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;
}
}
}
回答6:
public Class Person
{
private int _id;
public int ID
{
get{ MyMethod(); return _id; }
set{ _id = value; }
}
// etc. etc. .....
}
回答7:
private bool _pp; public bool Propery { get { // your code} set { _pp = value; } }
回答8:
I think you're looking for an Aspect Oriented Framework.
回答9:
If you can't change the class itself, you might consider using an extension method to get the name. This will change the way you access the data, so it might not be an option either. This is how you'd do it, if you're interested:
public static class PersonExtensions
{
public static string GetName(this Person p)
{
foo();
return p.Name;
}
}
You would then access the name this way:
Person myPerson = new Person();
string name = myPerson.GetName(); // Also calls foo() for you extra processing
Hope this helps.
来源:https://stackoverflow.com/questions/2691494/intercept-call-to-property-get-method-in-c-sharp