2011-03-17 2 views
0

나는 특성을 가지고 일하기 시작했으며,이 예제에서 코드는 PostSharp 2.0을 사용하여 작성되었다.어쨌든 속성에서 데이터를 추출하거나 저장 하시겠습니까?

내가 원하는 것은 Stopwatch 속성을 가진 메소드이거나 호출하는 메소드가 경과 시간에 액세스 할 수 있다는 것입니다.

나는 현재 C# 4.0

샘플 속성 코드를 사용하여이 코드를 쓰고 있어요 :

[Serializable] 
public class StopwatchAttribute : OnMethodBoundaryAspect 
{ 
    public override void OnEntry(MethodExecutionArgs args) 
    { 
     // Create new stopwatch 
     Stopwatch stopwatch = new Stopwatch(); 

     // Begin timing 
     stopwatch.Start(); 

     args.MethodExecutionTag = stopwatch; 
    } 

    public override void OnExit(MethodExecutionArgs args) 
    { 
     Stopwatch stopwatch = (Stopwatch)args.MethodExecutionTag; 

     // Stop timing 
     stopwatch.Stop(); 

     // Write result 
     Debug.WriteLine("Time elapsed: {0} ms", stopwatch.Elapsed); 
    } 
} 

가 속성

[Stopwatch] 
public string Search(string LineNo) 
{ 
    // Search for something 
    // Is it possible to know how long (from Stopwatch attribute) Search took 
} 

public void CallSearch 
{ 
    string x = Search("xyz"); 
    // Is it possible to know how long (from Stopwatch attribute) Search took 
} 

를 사용하여 나는 경과 시간의 출력을 얻을.

그러나 Elapsed Time Out을 보낼 수 있도록 확장해야합니다.

이상적으로 Search의 길이는 CallSearch에서 가져 왔지만, Search에서 결과를 얻은 다음 다시 시도해도 괜찮습니다.

해결 방법은 현재 "Hole in the Middle" 패턴을 사용하고 있습니다.

감사합니다.

+1

은 내가 사용 비슷한 일을했던 [유니티 차단] (http://pnpguidance.net/Post/UnityInterceptionExtensionExampleTransparentProxyPolicyInjectorHandlerAttributeICallHandler.aspx) –

+0

@Sanjeevakumar 내가 네 제공된 링크 내가 무엇을 찾고 어떻게하는지 이해할 수 없었다 죄송합니다. 자세한 내용을 제공해주십시오. –

답변

1

저는 속성이 읽기 전용이며 완전히 컴파일 타임에 결정됩니다 믿습니다. 코드를 컴파일 한 후에는 속성에 영향을 줄 수 없습니다. 아마도 executon 시간을 추적하도록 표시된 각 메서드의 마지막 실행 시간을 추적하기 위해 정적 사전 (대리자 또는 MemberInfo를 실행 시간 값에 매핑)을 유지할 수 있습니까?

+0

제안 해 주셔서 감사합니다. –

1

글쎄, 속성의 변수는 메소드 종료 후에 사라질 것입니다. 이렇게하려면 로그 또는 데이터의 다른 영구 소스를 평가해야합니다. 정적 목록이나 이와 비슷한 데이터를 작성할 수는 있지만 작성할 수있는 코드가 없으므로 속성 자체를 조사하여 해당 속성을 사용하는 메소드의 마지막 실행 시간을 결정합니다 (속성 클래스에 동일한 영구 저장소를 검사합니다.

작성한 것처럼이 속성은 CLR에 의해 특별한 방법으로 사용되는 클래스 일뿐입니다. 애스펙트 지향 속성의 존재 여부를 확인하고 필요에 따라 인스턴스를 생성 한 다음 필요에 따라 모든 핸들러를 호출합니다. 클래스는 런타임에서 필요하지만 범위 내에 있고 일단 그렇지 않으면 GCed입니다. 애스펙트 지향적 인 목적의 범위를 벗어나는 애트리뷰트를 사용하려면, 액티베이터를 사용하여 유형에 대한 작업을 수행하거나 액티베이터를 사용하여 인스턴스를 새로 작성하십시오.

한 가지; 속성은 정적 속성을 가질 수 있습니다. 따라서 정적 Stopwatch 인스턴스를 정의하고 OnExit에서 가장 최근에 중지 한 Stopwatch로 설정할 수 있습니다. 이렇게하면 속성으로 장식 된 마지막으로 실행 된 메서드의 시간을 정적으로 결정할 수 있습니다.

+0

제안 해 주셔서 감사합니다. 정적 속성을 만들어보고이를 통해 작업 할 수 있는지 확인합니다. –

0

가능한 해결 방법 (죄송합니다, 나는 그것을 테스트하지 못했지만, 아이디어가 명확해야) :

[Serializable] 
public class StopwatchAttribute : OnMethodBoundaryAspect 
{ 
    [ThreadStatic] 
    private static Stopwatch stopwatch = null; 

    public override void OnEntry(MethodExecutionArgs args) 
    { 
     var sw = stopwatch ?? new Stopwatch(); 
     args.MethodExecutionTag = sw; // Better to move this line before .Start 
     sw.Start(); 
    } 

    public override void OnExit(MethodExecutionArgs args) 
    { 
     var sw = (Stopwatch) args.MethodExecutionTag; 
     sw.Stop(); 
     Debug.WriteLine("Time elapsed: {0} ms", sw.Elapsed); 
    } 

    public static Stopwatch Measure(Action action) 
    { 
     var oldStopwatch = stopwatch; 
     stopwatch = new Stopwatch(); 
     try { 
      // !!! Btw, you can measure everything right here. 
      action.Invoke(); 
      return stopwatch; 
     } 
     finally { 
      stopwatch = oldStopwatch; 
     } 
    } 
} 

묵시적 사용 : 그래서 당신이 볼로

[Stopwatch] 
public string Search(string LineNo) 
{ 
    // Search for something 
    // Is it possible to know how long (from Stopwatch attribute) Search took 
} 

public void CallSearch 
{ 
    var stopwatch = StopwatchAttribute.Measure(() => { 
     string x = Search("xyz"); 
    }); 
    Console.WriteLine("Time elapsed: {0} ms", stopwatch.Elapsed); 
} 

은 PostSharp 사용하지 보인다 여기서 꽤 필요합니다.이러한 타이밍을 기록하는 데 사용할 수 있지만 비슷한 접근 방식이나 자체 로그 액세스 API를 사용하여 기록 된 시간을 가져와야합니다.

+0

예 "MIddle의 구멍"패턴을 다소간 사용합니다. 저는 주로 학습 과정으로 Attributes를 사용하여이 작업을 수행하려고합니다. –

0

특성은 디자인 타임에 클래스, 속성 및 메서드에 설명을 추가 할 때만 사용해야하며이를 리플렉션을 통해 런타임에 검사 할 수 있습니다.

비즈니스 로직을 저장하는 데 사용하지 않을 것입니다.

참조 용으로 great article입니다.