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.
Related
I have a project where I do this:
public class Stuff
{
[ExecuteOnComputer("192.168.1.2")]
public void methodA()
{
return "ok";
}
[ExecuteOnComputer("192.168.1.3")]
public void methodB()
{
return methodA();
}
}
I use the ExecuteOnComputer attribute in an Executor class that dispatches the call to the computer located at the IP address specified in the attribute. (this is not the exact thing I am doing but is similar enough for the purpose of simplifying the question).
Now, I want to ensure that if a method tagged with the ExecuteOnComputer calls another method tagged with the ExecuteOnComputer attribute, then something alerts me if the 2 attributes have a different IP address (the example above should alert me somehow that the attributes are not well defined).
Obviously, the C# syntax is correct, and it's impossible to use reflection on the produced DLL, because reflection can't tell me that methodB calls methodA.
So I am thinking that a way to do this would be to have an extension in Visual Studio check that for me during editing or compile time. I need some Roslyn code to analyze the call tree from methodB.
There seems to be some solutions out there, but the docs are not great. I was hoping there would be something available with some Roslyn/VS extension boilerplate code already done.
Can anyone help me with this?
I have many Model-Classes which implement the INotifyPropertyChanged-Interface in order to update the UI when value changed.
Sadly the properties must be written fully to support this feature. I decreased my code already by using the 'SetPropertyValue'-Method() in BaseClass.
private string _title;
public string Title
{
get { return title; }
set { SetPropertyValue("Title", ref _title, value ); }
}
But with 20 properties written like that in one file it is not so simple to understand the content of the file in a short time unlike to the auto implemented properties.
What I want is to write my Property like this:
[NotifyChanged]
public string Title { get; set; }
I checked already PostSharp but in the free version there are only 10 classes included (it's a hobby project so I don't want to pay much money).
Is there any possibility to attach my one logic to C#-Compiler (as a pre-compiler)?
Such a feature I would like to use on different places in my code to reduce unneccessary coding lines (especially for auto-properties).
Or maybee a VisulStudio-Extension?
Try Fody. It is library which modifies IL code during build process using dedicated msbuild task.
It has large base of addins including PropertyChanged which should suit in your scenario.
This addin gives you attribute ImplementPropertyChanged which you can apply to a class. Then Fody will generate code implementing INotifyPropertyChanged to all auto-properties.
Second option if you have ReSharper version 7 or higher. It has refactoring which can help you with implementation of INotifyPropertyChanges. For example it can transform auto-property to "normal" property implementing the interface.
Thou it may not fully satisfy you - this approach may be interesting for you because it does not involve additional libraries and assembly modification.
Another option is Castle DynamicProxy. The difference between PostSharp and Fody is that DynamicProxy generates its proxies on the fly at runtime.
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)]
I have been playing along with AOP for years, but didnt become 100% satisfied with the solutions.
AOP Frameworks with runtime weaving, like Spring.AOP, cannot change the interface of a class.
With post compile time Frameworks like Postsharp (anyone knows someone else ?) you can.
Check this sample out, it adds INotifyPropertyChanged implementation to your class. -> http://www.postsharp.net/model/inotifypropertychanged
This AOP feature is really great, but you run in troubles very soon...
If you want to access the new Interface within the hosting assembly, you cannot compile,
because the interface is added AFTER compilation.
so you get a "PropertyChanged is not defined"-error.
So you have to ugly workaround this, by seperating the classes into another assembly, so you can use those AOP advantages.
I remember, i ran into the same "Post compile time"-troubles using a T4-Template that generates source code, based on the reflected infos of a assembly. OK so post compile time is sometimes too late...
What i am looking for is a solution, where the source code of the class is parsed via a visual studio user defined tool, und then generates the code in a C# file, in a partial class.
(so all AOP applied classes have to be partial)
So its kind of "Pre-Compile-Time AOP".
This should definitly be possible, and could be done via using NRefactory as Code Parser.
Furthermore, Visual Studio would like this much more, than a post-compile modification.
So this solution eliminates disadvantages of post compile time weavers.
but does not give you all the features of AOP. But together with an AOP-Framework, this should be awsome.
Does anyone know a framework like this, or a discussion ?!
what do you think ?
kind regards, thomas
since you and I have already been corresponding on using SNAP as a viable alternative, I thought I'd post a summary of our discussion here for the benefit of those who are looking for a similar solution.
In short, SNAP provides a runtime AOP framework that doesn't change your code in any way. There's no post-compile step, just runtime interception which is predictable and easy to use.
What your are looking for is pMixins. It's still in beta, but it does exactly what you are looking for: design-time weaving. AOP code is generated into a partial code-behind class so it's available at design-time.
So this means you can do this in one file and the compiler is happy, visual studio is happy, resharper is happy:
Define an interface:
public interface ISomeInterface
{
void SomeMethod();
}
Create an implementation of the interface (I call this a Mixin):
public class SomeInterfaceImplementation : ISomeInterface
{
public void SomeMethod()
{
//implementation
}
}
Define a Target file (which will consume the Mixin):
[pMixin(Mixin = typeof(SomeInterfaceImplementation))]
public partial class Target { }
Let's create a utility class that works with SomeInterface and SomeInterfaceImplementation:
public class Utility
{
public void DoSomeWorkOnSomeInterface(ISomeInterface obj)
{
obj.SomeMethod();
}
public void DoSomeWorkOnImplementation(SomeInterfaceImplementation obj)
{
obj.SomeMethod();
}
}
And now let's see it all work together:
class Program
{
private static void Main(string[] args)
{
//Call the mixed in method
new Target().SomeMethod();
//Target implements ISomeInterface is code-behind
new Utility().DoSomeWorkOnSomeInterface(new Target());
//Target has an implicit conversion operator to
//SomeInterfaceImplementation in code-behind
new Utility().DoSomeWorkOnImplementation(new Target());
}
}
The reason this works is because as soon as you save the file, the pMixins code generator immediately does design-time weaving and updates the code-behind file. It adds the SomeMethod directly to Target, updates Target's class definition to implement ISomeInterface and creates conversion operators.
Disclosure: I am on the pMixins development team.
In the case of PostSharp, you can access an interface introduced at post-compile-time by using the method Post.Cast, which is a kind of cast operator that is verified at post-compile-time. See http://doc.postsharp.net/postsharp-3.0/Content.aspx/PostSharp-3.0.chm/html/M_PostSharp_Post_Cast__2.htm for documentation.
I have various individual methods which all need to perform the same functions before continuing on with their own implementation. Now I could implement these functions in each method, but I was wondering if there's a way to exploit attributes to do this? As a very simple example, all network calls have to check for a network connection.
public void GetPage(string url)
{
if(IsNetworkConnected())
...
else
...
}
This would work, but I'd have to call the IsNetworkConnected method for each method that uses the network and handle it individually. Instead, I'd like to do this
[NetworkCall]
public void GetPage(string url)
{
...
}
If the network is unavailable, an error method is called instead and GetPage is ignored, otherwise GetPage is invoked.
This sounds very much like Aspect Orientated Programming, but I don't want to implement an entire framework for a few calls. This is more of a learning exercise than an implementation one, so I was curious as to how something like this would be best implemented.
You can use PostSharp, it is aspect-oriented framework for .NET, it seems quite easy to use:
static void Main(string[] args)
{
Foo();
}
[IgnoreMethod(IsIgnored=true)]
public static void Foo()
{
Console.WriteLine("Executing Foo()...");
}
[Serializable]
public class IgnoreMethodAttribute : PostSharp.Aspects.MethodInterceptionAspect
{
public bool IsIgnored { get; set; }
public override void OnInvoke(PostSharp.Aspects.MethodInterceptionArgs args)
{
if (IsIgnored)
{
return;
}
base.OnInvoke(args);
}
}
Method-Level Aspects feature is available in the free edition: http://www.sharpcrafters.com/purchase/compare
Run-Time Performance:
Because PostSharp is a compiler technology, most of the expensive work is done at build time, so that applications start quickly and execute fast. When generating code, PostSharp takes the assumption that calling a virtual method or getting a static field is an expensive operation. Contrary to rumor, PostSharp does not use System.Reflection at run time.
http://www.sharpcrafters.com/postsharp/performance
I don't think you can do this with attributes only, because they are not executed by the runtime if you're not actively doing something with them. A lightweight approach would be Ninject with Interceptions extension, it is a framework, but a very thin one, and one you might already be using for DI anyway.
Another option, but a bit more involved, could be based on MEF, and then you can use attributes and do something during with them during activation.
You're right, it sounds a lot like AOP.
What you're after sounds like compile time weaving? I.e. the attribute is turned into additional code by the compiler.
You could look at how to implement this...
Generating additional code through a custom attribute
http://www.cs.columbia.edu/~eaddy/wicca/ &
http://www.sharpcrafters.com/aop.net/compiletime-weaving
all refer to tools and techniques for doing this.
Or you could use an AOP framework. IMHO, you should look at AOP frameworks.