2012-10-09 4 views
3

저는 PostSharp에서 다양한 개념을 연구하고 있습니다.PostSharp를 사용하여 C#에서 생성자에 애스펙트 적용

업데이트 :

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 :이

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"); 
     } 
    } 

} 

로 내 프로그램 클래스와

1) 일부 추적 측면 클래스와 내 측면 클래스는

입니다) TraceAspectProvid 클래스 :

using System; using System.Collections.Generic; using System.Linq; using System.Text; PostSharp.Aspects를 사용하는 ; using System.Reflection;

네임 스페이스 MyProviders { 공용 클래스 TraceAspectProvider : IAspectProvider { 읽기 전용 SomeTracingAspect aspectToApply = 새로운 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); 
     } 

} } }

그리고 난 솔루션과 응답을 기다리는

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) 

으로 오류를 얻고있다

"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" 

으로 내 측면 파일은 주어진

+0

@DustinDavis이 문제와 관련하여 해결책을 제공해 줄 수 있습니까? – GowthamanSS

+0

현재 접근 방식에 어떤 문제가 있습니까? –

답변

3

여러분의 주요 문제는 제 3 자 라이브러리 (mscorlib)에 관한 측면을 적용하려는 것입니다. 도움이 될 Dustin's blog post on how to do this을 살펴보십시오. PostSharp는 공식적으로 이것을지지하지 않습니다.

생성자에 애스펙트를 적용하려면 TypeLevelAspectMulticastPointcutits Targets set to e.g. InstanceConstructor으로 사용할 수 있습니다.

TypeLevelAspect을 사용할 수없는 경우 (예 : 이벤트에 애스펙트를 적용하려는 경우) 나는 이전에 OnMethodEntryAdviceMethodPointCut을 사용했습니다. 이렇게하면 생성자를 수동으로 검색 할 수 있습니다.

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

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

내가 생성자 can be found on my blog에서 이벤트를 초기화하려면이 옵션을 적용하는 방법을 좀 더 확장 된 논의.

이 클래스의 최신 완전한 소스 코드 can be found on github. 블로그 게시물 이후 몇 가지 변경 사항을 만들었지 만 생성자를 타겟팅하는 원칙은 동일하게 유지됩니다.

+0

귀하의 솔루션에 감사드립니다 – GowthamanSS

+0

그냥 내 문제를 해결하기 위해 StreamWriter로 [OnMethodEntryAdvice, MethodPointcut ("SelectConstructors")]의 SelectConstructors 코드를 바꿀 수 있습니까 – GowthamanSS

+0

@GowthamanSS 나는 100 % 확신 할 수 없습니다. 인수를 조정할 수 있지만 시도해 보시길 권합니다.하지만,'OnConstructorEntry()'메서드 내에서 생성자의 시작 부분에 삽입해야 할 코드를 정의하십시오. 'args.Arguments'를 통해 생성자 인수에 접근 할 수 있습니다. –