Wrapping method call with PostSharp - c#

Is there any way to wrap a method call with PostSharp? I have to add code around/outside a specific call.
The OnMethodBound add the code inside the specified method and the MethodInterception aspect redirects the call to the aspect, but I have to to add code outside the call.
Example:
Without aspect:
...
call();
...
With aspect:
beforePart();
call();
afterPart();

Currently, the only scenario in which PostSharp weaves the aspect around the call site is when you apply that aspect to a method in the referenced assembly.
When applying an aspect in your project, you can set the name of the external assembly in the AttributeTargetAssemblies property.
[Log(AttributeTargetAssemblies = "SomeLibrary", ...)]
PostSharp, of course, will not modify the existing external assembly, instead it will weave the aspect in your project's assembly around the calls to the referenced assembly.
Applying the aspect to the calls of the methods from the same assembly is not currently supported. In most scenarios this is not required, or there should be a reasonable workaround.
Maybe we'll be able to solve this if you provide more details about your synchronized method and why it's not possible to use method interception.
Update.
The possible workaround is to introduce the synchronization locks using aspects. You can write a custom OnMethodBoundaryAspect or use SynchronizedAttribute from the Threading Pattern Library.
Then you can use Aspect Dependency or Aspect Priority to make sure that the measuring aspect is introduced before the threading aspect. This way the behavior will be the same as when introducing the measuring aspect around the call site.
[Serializable]
[AspectTypeDependency(AspectDependencyAction.Order,
AspectDependencyPosition.Before,
typeof(SynchronizedAttribute))]
public class MeasureTimeAttribute : OnMethodBoundaryAspect
{
// ...
}

I had similar requirement and I wrote a logging aspect for all database calls I make with external library which is Dapper. I created an aspect:
[MulticastAttributeUsage(MulticastTargets.Method)]
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public sealed class SqlLogger : MethodInterceptionAspect
{
public override void OnInvoke(MethodInterceptionArgs args)
{
// logging code goes here
base.OnInvoke(args);
}
}
And then I registered it on assembly level:
[assembly: SqlLogger(AttributeTargetAssemblies = "Dapper", AttributePriority = 1)]

Related

Prevent Use of Method in Another Assembly

We are using a 3rd party assembly which has a problematic method. Is there some way to alert our developers that the method should not be used, preferably at compile time but run-time is ok too. Something like an Obsolete attribute but for another assembly. I can't override the method because it's not virtual.
The only way I can see that this is possible is to wrap the API in your own assembly and get the developers to use your assembly instead of the provided one.
using MyAPI;
public class MyWrapper
{
private MyAPI _api;
public MyWrapper()
{
_api = new MyAPI(); //Especially if you want to do some inits
}
public void APIMethod()
{
_api.APIMethod();
}
}
My using the same method names, it will allow your developers to just replace the instantiation of the object with the new class, or even more cheekily, call the class the same thing and change the namespace.
Then, you can either omit the offending method(s) or mark them as obsolete.
You could even use the T4 templates to generate the code for you so you can regenerate if the API changes. If you use reflection, you may not even have to write the T4...
For nmore info on T4 - https://msdn.microsoft.com/en-us/library/dd820614.aspx
Hope this was useful.

TargetedPatchingOptOut and other attributes on abstract methods

Since, attributes such as TargetedPatchingOptOut aren't handled inside the framework, do the attributes propagate to the inherited classes during the optimization?
Eg:
public abstract class TestBase
{
[TargetedPatchingOptOut("Optimize across boundaries")]
public abstract void TestFunc();
}
public class Test : TestBase
{
// Is re-defining attributes like these necessary?
public override void TestFunc()
{
throw new NotImplementedException();
}
}
Also, does the JIT compiler (ever/always) lookup inherited attributes?
Note: Although the specific functionality above can be figured out easily by examining the JIT instructions on WinDbg with a few
(tediously) extravagant methods, I appreciate any insights on how its
implemented, as it is not impossible for the JIT compiler to behave
very differently for different attributes without knowing its exact
implementation.
Update:
I made a wrong assumption that the TargetedPatchingOptOut is handled by the JIT compiler, but while it is infact handled by NGen. The answer for this specific case has been answered clearly by #Hans Passant.
I think its safe to guess, each of the internal tools utilize the attributes by the same rules as given by the AttributeUsage flag.
Whether an attribute is visible on a derived class by default is determined by the AttributeUsageAttribute.Inherited property. Which is false for this attribute:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor,
AllowMultiple = false, Inherited = false)]
public sealed class TargetedPatchingOptOutAttribute : Attribute {
// etc...
}
It is not exclusive, a method like Type.GetCustomAttribute() also has an inherit argument to allow overriding the default.
Do be careful about making assumptions about what tooling reads an attribute. [TargetedPatchingOptOut] is almost certainly not read by the jitter. It is used to determine if Ngen.exe needs to run to re-create the native image of an assembly when an update is deployed. I don't know what the tooling looks like, the only thing that makes sense to me is that this is done on Microsoft machine in Redmond.

Using HandlerAttribute in clients without referencing Unity but using own framework

We are building a framework that makes use of PolicyInjection to perform certain tasks. We make use of attributes for this. This code is written in a seperate framework solution.
Out CallHandler could look as follows:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Method)]
public class MyCallHandlerAttribute : HandlerAttribute
{
...
}
And in Unity we have:
namespace Microsoft.Practices.Unity.InterceptionExtension
{
public abstract class HandlerAttribute : Attribute
{
...
}
}
In the client solution we have a call handler (MyCallHandler) that we register using Unity. To execute the code in the call handler we need to add the attribute above the class/method/property of the model:
[MyCallHandler(params[])]
public class MyModel : IMyModel
{
...
}
The problem now is that to use MyCallHandler we need a reference to the PolicyInjection DLL for the compiler to understand that a HandlerAttribute is an Attribute. If there is no reference we get a 'MyCallHandler' is not an attribute class warning (error when compiling).
How can we implement this in such a way without needing to reference the Unity DLL in our client solution(s), but only our framework DLLs?
Ok. So after some research and finding similar, but much simpler examples, I've come to the conclusion that this is not feasible unless you include a large (if not all) the Unity code in your project.
What I did try is to create my own policy injection behavior that looks only for MyCallHandler attributes rather than any HandlerAttribute. This means that I can let MyCallHandlerAttribute implement Attribute instead of HandlerAttribute. So MyModel knows that MyCallHandlerAttribute is an attribute.
This worked like a charm, but the problem now was that MyModel has no idea what ICallHandler is. Again, this is a Unity defined interface. This is likely to continue for several other things (IUnityContainer and whatnot).
I can provide code examples of what I did if anyone is interested.

How does OnMethodBoundaryAspect works?

I've founded the OnMethodBoundaryAspect attribute in the PostSharp library. It can intercept entry and exit from method like this:
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method, Inheritance = MulticastInheritance.Multicast)]
public class InterceptAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{ }
public override void OnExit(MethodExecutionArgs args)
{ }
}
public class A
{
[Intercept]
public void foo() { }
}
And my question is "How does it work?" What should I do to write my own attribute, that will be able to intercept entry and exit from method (without PostSharp using ofcourse)?
First of all, I'd recommend reading following documentation for internal workings (the "how does it work" sections and others). Basically, the attributes are translated into relevant code at the build time (actually, mostly after the build but still while building). There's a notion of MSBuild task that specifies the code to be run during the build process. The code executes after the compilation is done and looks for specific attributes (like InterceptAttribute) and may perform changes to the compiled code. Runtime edits to the code may be executed while using Mono.Cecil library (it allows to inject/remove IL code). Once again, to clarify:
The code is built with attributes assigned.
During the build, specific code is called per BuildTasks written
BuildTasks use reflection to find pieces of code that contain necessary attributes
BuildTasks use Mono.Cecil to inject code dynamically to those pieces found
Build is complete. Your compiled dll now contains not only the code written, but also the attributes changed into some code. I'd suggest looking at the assembly with ILSpy or similar decompilers to see the difference between your initial code and generated one.
I'd recommend looking at KindOfMagic codes to see how automatic INotifyPropertyChanged's RaisePropertyChanged is implemented as attribute. It provides valuable insights into creating custom aspects, though it may prove hard and tedious process.

C#: Wrapping methods in other methods

Is there a way to wrap methods in other methods transparently in C#? I want to achieve what is done by Moose's around functionality: http://search.cpan.org/perldoc?Moose::Manual::MethodModifiers
EDIT: And by transparent I mean without modifying the original method.
I think you're looking for what's termed Aspect Oriented Programming. There are many C# libraries to help with this. One is called PostSharp (The free version of PostSharp supports this functionality). Here is an example similar to the moose example. This creates a Trace Attribute which you can use on other methods to tack on this extra functionality:
[Serializable]
public class TraceAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args )
{
Trace.WriteLine("about to call method");
}
public override void OnExit(MethodExecutionArgs args)
{
Trace.WriteLine("just finished calling method");
}
}
You would add it to method "Foo" by placing the Trace attribute right before it:
[Trace]
public void Foo() { /* ... */ }
Now when Foo executes, the above OnEntry method will run before it, and OnExit will run right after.
Indeed, they're called "delegates" in .NET. See:
http://alexdresko.com/2010/07/25/using-idisposable-objects-responsibly-the-easy-way/
http://alexdresko.com/2010/07/27/using-delegates-to-eliminate-duplicate-code/
for help.
You can achieve the same effect by utilizing a dynamic proxy. An example is the Castle Dynamic Proxy.
Such frameworks leverage the C# reflection facilities to construct 'proxy' or 'wrapper' classes. So, keep that in mind. There is a certain amount of overhead because of this. Alternatively you can use frameworks that can create classes statically via code generation.
No, not the way it's done in Moose. You might want to look into some AOP library.
Some isolation libraries implement functionality that allows replacing calls to methods with "detours" or mock methods. You may be able to use the same functionality to implement the interception you are referring to. For more details, check the following:
Rhino Mocks stubs and mocks are only good for interfaces?
http://research.microsoft.com/en-us/projects/moles/
http://www.typemock.com/typemock-isolator-product3/

Categories