How to replace auto-implemented c# get body at runtime or compile time?
- by qstarin
I've been trying to figure this out all night, but I guess my knowledge of the .Net Framework just isn't that deep and the problem doesn't exactly Google well, but if I can get a nod in the right direction I'm sure I can implement it, one way or another.
I'd like to be able to declare a property decorated with a custom attribute as such:
public MyClass {
[ReplaceWithExpressionFrom(typeof(SomeOtherClass))]
public virtual bool MyProperty { get; }
}
public SomeOtherClass : IExpressionHolder<MyClass, bool> {
...
}
public interface IExpressionHolder<TArg, TResult> {
Expression<Func<TArg, TResult>> Expression { get; }
}
And then somehow - this is the part I'm having trouble figuring - replace the automatically generated implementation of that getter with a piece of custom code, something like:
Type expressionHolderType = LookupAttributeCtorArgTypeInDeclarationOfPropertyWereReplacing();
return ReplaceWithExpressionFromAttribute.GetCompiledExpressionFrom(expressionHolderType)(this);
The main thing I'm not sure how to do is replace the automatic implementation of the get.
The first thing that came to mind was PostSharp, but that's a more complicated dependency than I care for. I'd much prefer a way to code it without using post-processing attached to the build (I think that's the jist of how PostSharp sinks its hooks in anyway).
The other part of this I'm not so sure about is how to retrieve the type parameter passed to the particular instantiation of the ReplaceWithExpressionFrom attribute (where it decorates the property whose body I want to replace; in other words, how do I get typeof(SomeOtherClass) where I'm coding the get body replacement). I plan to cache compiled expressions from concrete instances of IExpressionHolder, as I don't want to do that every time the property gets retrieved.
I figure this has just got to be possible. At the very least I figure I should be able to search an assembly for any method decorated with the attribute and somehow proxy the class or just replace the IL or .. something? And I'd like to make the integration as smooth as possible, so if this can be done without explicitly calling a registration or initialization method somewhere that'd be super great.
Thanks!