Applying aspect on constructor in c# using PostSharp

不羁岁月 提交于 2019-11-29 23:35:18

问题


I am working on various concepts in PostSharp.

Updated:

This is my program class as

namespace myconstructor
{
    class Program
    {
        static void Main(string[] args)
        {
            createfolder();
            streamfolder();
        }
        public static void createfolder()
        {
            File.Create("E:/samplefile.txt");

        }
        public static void streamfolder()
        {
            StreamWriter sw = new StreamWriter("E:/samplestream.txt");
        }
    }

}

and my aspect class as

1)some tracing aspect class :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PostSharp.Extensibility;
using PostSharp.Aspects.Dependencies;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using System.Reflection;
using System.Linq.Expressions;

namespace MyProviders
{
    [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Event)]
    [MulticastAttributeUsage(MulticastTargets.Event, AllowMultiple = false)]
    [AspectTypeDependency(AspectDependencyAction.Commute,typeof(SomeTracingAspect))]
    [Serializable]
    public class SomeTracingAspect : EventLevelAspect
    {
        [OnMethodEntryAdvice, MethodPointcut("SelectConstructors")]
        public void OnConstructorEntry(MethodExecutionArgs args)
        {
            args.ReturnValue = "aspectfile"; 
        }

        IEnumerable<ConstructorInfo> SelectConstructors(EventInfo target)
        {
            return target.DeclaringType.GetConstructors(
                        BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        }

        public override void RuntimeInitialize(EventInfo eventInfo)
        {
            base.RuntimeInitialize(eventInfo);

        }
    }

}

2)TraceAspectProvider class:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using PostSharp.Aspects; using System.Reflection;

namespace MyProviders { public class TraceAspectProvider : IAspectProvider { readonly SomeTracingAspect aspectToApply = new SomeTracingAspect();

    public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
    {
        Assembly assembly = (Assembly)targetElement;

        List<AspectInstance> instances = new List<AspectInstance>();
        foreach (Type type in assembly.GetTypes())
        {
            ProcessType(type, instances);
        }

        return instances;
    }

    private void ProcessType(Type type, List<AspectInstance> instances)
    {
        foreach (ConstructorInfo target in type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
        {
            instances.Add(new AspectInstance(target, aspectToApply));
        }

        foreach (Type nestedType in type.GetNestedTypes())
        {
            ProcessType(nestedType, instances);
        }

} } }

and my aspect file given as

 "C:\Program Files\PostSharp 2.1\Release\postsharp.4.0-x86-cil.exe" "D:\fileaspecttest\myconstructor.exe" /p:AspectProviders=MyProviders.AspectProvider,MyProviders /p:Output="D:\fileaspecttest\myaspect.exe"

i am getting error as

 error PS0125: An unexpected exception occured when executing user code: System.ArgumentNullException: Value cannot be null.
 error PS0125: Parameter name: type
 error PS0125:    at System.Activator.CreateInstance(Type type, Boolean nonPublic)
 error PS0125:    at ^7HtKTJrYMoHj.^kfEQVEmN.^jK8C2yxJ()
 error PS0125:    at PostSharp.Sdk.Utilities.ExceptionHelper.ExecuteUserCode[T](MessageLocation messageLocation, Func`1 userCode, Type[] acceptableExceptions)

Waiting for your solution and responses


回答1:


I think your main problem is you are trying to apply aspects on 3th party libraries (mscorlib). You can take a look at Dustin's blog post on how to do this which might help you out. Do take into account officially this isn't supported by PostSharp.

In order to apply aspects to a constructor you can probably use a TypeLevelAspect and a MulticastPointcut with its Targets set to e.g. InstanceConstructor.

When you can't use a TypeLevelAspect (e.g. you want to apply the aspect to events) I previously used a OnMethodEntryAdvice and a MethodPointCut. This allows you to search for the constructors manually.

[OnMethodEntryAdvice, MethodPointcut( "SelectConstructors" )]
public void OnConstructorEntry( MethodExecutionArgs args )
{
    ...
}

IEnumerable<ConstructorInfo> SelectConstructors( EventInfo target )
{
    return target.DeclaringType.GetConstructors(
        BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
}

A more extended discussion how I applied this to initialize events from the constructor can be found on my blog.

The latest complete source code of this class can be found on github. I've made several changes since the blog post, but the principle of targeting constructors remains the same.



来源:https://stackoverflow.com/questions/12798391/applying-aspect-on-constructor-in-c-sharp-using-postsharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!