How to inject an attribute using a PostSharp attribute?
See http://www.sharpcrafters.com/blog/post/PostSharp-Principals-Day-12-e28093-Aspect-Providers-e28093-Part-1.aspx
Here is a working example. Applying this aspect to a class will apply the XmlIgnore attribute to any public property that does not already have XmlElement or XmlAttribute applied to it. the trick is using the CustomAttributeIntroductioinAspect that is built in to Postsharp. You just need to instantiate an instance specifying the attribute type and contructor details, then create a provider to apply it to the target(s).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PostSharp.Extensibility;
using PostSharp.Aspects;
using PostSharp.Reflection;
using System.Xml.Serialization;
namespace ApplyingAttributes
{
[MulticastAttributeUsage(MulticastTargets.Field | MulticastTargets.Property,
TargetMemberAttributes = MulticastAttributes.Public | MulticastAttributes.Instance)]
public sealed class AddXmlIgnoreAttribute : LocationLevelAspect, IAspectProvider
{
private static readonly CustomAttributeIntroductionAspect customAttributeIntroductionAspect =
new CustomAttributeIntroductionAspect(
new ObjectConstruction(typeof(XmlIgnoreAttribute).GetConstructor(Type.EmptyTypes)));
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
LocationInfo memberInfo = (LocationInfo)targetElement;
if (memberInfo.PropertyInfo.IsDefined(typeof(XmlElementAttribute), false) ||
memberInfo.PropertyInfo.IsDefined(typeof(XmlAttributeAttribute), false))
yield break;
yield return new AspectInstance(memberInfo.PropertyInfo, customAttributeIntroductionAspect);
}
}
}
To use attributes, specifying parameters, I use
public class MyAspect : TypeLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
yield return Create<MethodInfo>(mi, "Value");
}
private AspectInstance Create<T>(T target, string newName)
{
var x = new CustomAttributeIntroductionAspect(
new ObjectConstruction(typeof(NewMethodName).GetConstructor(new Type[] { typeof(string) }), new object[] { newName })
);
return new AspectInstance(target, x);
}
}
AOP Postsharp - Aspect attributes not working
I figured it out after hard trying. When we want to use Postsharp on our project, we must add Postsharp VS extension. After installing postsharp extension, we must logon and check our postsharp policy to target our classes with postsharp attributes (or custom derived postsharp attributes).
Postsharp provide 10 target class for express edition. After compile check out for output for postsharp process, if it succeed, postsharp inject IL code to our method that we marked with aspect attributes.
If we did everything right, we can get sessions,users etc everything can be logged without any workaround also provide dead easy caching mechanism.
Its all about postsharp VS Extension & Policy settings.
Possible to inject dynamic code using PostSharp AOP
The answer is no for the described use case. PostSharp runs after the C# compilation has already completed and processes the binary assembly. At this point it's already too late to add a string input for C# compiler.
Native PostSharp attributes are ignored if injected using Custom Attributes
You can provide DependencyPropertyAttribute
directly as an aspect to the target property instead of going via CustomAttributeIntroductionAspect
. For example:
yield return new AspectInstance(targetElement: property, aspect: new DependencyPropertyAttribute());
This is why DependencyPropertyAttribute
is not processed when introduced as an attribute:
PostSharp pipeline processes the assembly in several phases. The processing of the attributes is executed first, after that the aspect weavers are executed. If any aspect is emitting a new custom attribute during this phase, the attribute will not be processed by PostSharp anymore because the attribute processing phase has already completed.
PostSharp injecting dependency to aspect
This kind of thing is not possible mainly because attributes in general and aspects in particular can only have constant expressions in the constructor.
The constructor is called once per aspected target during compilation time. After this happens, the aspect is serialized (along with any internal data it may contain). It is deserialized during runtime, which means the constructor is not called at all. But there is no reason for it to be called; attribute constructors can only contain constant data that isn't liable to change. See about aspect lifetime here.
However, every aspected target still has its own instance of the aspect. This means you can do this during runtime initialization. You have a few options:
- Supply a string key parameter to the constructor, and then during runtime look up the appropriate object using the key (from a shared dictionary).
- Rely on the aspected type to have a property or field containing the object, and access it through reflection. It's recommended you do this during runtime initialization because reflection can cause performance problems.
How do I add arguments to PostSharp attributes?
Just declare a property
[Serializable]
public class MethodLoggingAttribute : OnMethodBoundaryAspect
{
private ILog _logger;
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
_logger = LogManager.GetLogger(eventArgs.Method.DeclaringType.ToString());
if(ShowParameters = true)
{
_logger.DebugFormat("Entered {0} with args:{1}", eventArgs.Method.Name, args);
}
else
{
_logger.DebugFormat("Entered {0}", eventArgs.Method.Name);
}
}
private bool m_ShowParameters;
public bool ShowParameters
{
get { return m_ShowParameters; }
set { m_ShowParameters = value; }
}
}
Then you can specify it in the way you have mentioned.
Related Topics
How to Sort a List<T> by Multiple T.Attributes
How to Hide Public Methods from Intellisense
C# MACro Definitions in Preprocessor
"Padding Is Invalid and Cannot Be Removed" Using Aesmanaged
Exclude a Field/Property from the Database with Entity Framework 4 & Code-First
How to Create a Generic Class from a String in C#
Newtonsoft.JSON Assembly Package Version Mismatch
How to Know the Repeating Decimal in a Fraction
Escape Quote in C# for JavaScript Consumption
Why Is Modulus Operator Not Working for Double in C#
Create Http Post Request and Receive Response Using C# Console Application
Opening Process and Changing Window Position
Piping in a File on the Command-Line Using System.Diagnostics.Process