C#:을 만드는 방법에 특성에서 방법을 트리거링 이벤트를 호출할 때?
-
03-07-2019 - |
문제
는 방법이 있 C#또는.순서는 일반적인 특성을 만들 방법에는 이벤트가 트리거 될 때 메소드가 호출될?이상적으로,내가 할 수 있 사용자 지정 작업을 실행하기 전과 후의 호출 방법입니다.
나는 뭔가 의미 다음과 같다:
[TriggersMyCustomAction()]
public void DoSomeStuff()
{
}
나는 완전히 우둔 그것을 어떻게 또는 그것 가능한 경우에는 모든하지만, 시스템입니다.Diagnostic.ConditionalAttribute 수도 비슷한 일이다.나는 확실하지 않지만.
편집:말 것도 그 때문에 상황의 특정한 경우,성능상 문제가 되지 않.
해결책
내가 이것을하는 방법을 아는 유일한 방법은 포스트 쇼트. 그것은 당신의 IL을 사후 처리하고 당신이 요청한 것과 같은 일을 할 수 있습니다.
다른 팁
이 개념에서 사용되는 MVC 웹 응용 프로그램입니다.
이 .NET Framework4.x 제공하는 몇 가지 특성이 있는 액션을 트리거,예를 들어: ExceptionFilterAttribute
(예외 처리), AuthorizeAttribute
(취급 authorization).모두에서 정의 System.Web.Http.Filters
.
당신은 예를 들어 정의한 당신의 자신의 권한 부여 특성이 다음과 같다:
public class myAuthorizationAttribute : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
// do any stuff here
// it will be invoked when the decorated method is called
if (CheckAuthorization(actionContext))
return true; // authorized
else
return false; // not authorized
}
}
그런 다음 컨트롤러 클래스를 장식하는 방법을 사용하여 당신의 권한 부여 다음과 같다:
[myAuthorization]
public HttpResponseMessage Post(string id)
{
// ... your code goes here
response = new HttpResponseMessage(HttpStatusCode.OK); // return OK status
return response;
}
할 때마다 Post
메소드가 호출될 것,전화 IsAuthorized
메서드 myAuthorization
특성 기 코드부 Post
메소드가 실행됩니다.
당신이 돌아 false
에 IsAuthorized
방법은,당신은 신호는 권한이 부여되지 않고 실행하는 방법 Post
이 중단됩니다.
을 이해하는 방법을 이 작품들에 대해 자세히 살펴보도록 하자는 다른 예를 들어:이 ExceptionFilter
, 할 수 있는 예외를 필터링을 사용하여 특성,사용법은 비슷한 위와 같이 대 AuthorizeAttribute
(당신이 찾을 수 있습니다에 대한 자세한 설명에 대해 그것의 사용 기).
그것을 사용하려면,파생 DivideByZeroExceptionFilter
에서 클래스 ExceptionFilterAttribute
으로 표시 기, 과 재정의 방법 OnException
:
public class DivideByZeroExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
if (actionExecutedContext.Exception is DivideByZeroException)
{
actionExecutedContext.Response = new HttpResponseMessage() {
Content = new StringContent("An error occured within the application.",
System.Text.Encoding.UTF8, "text/plain"),
StatusCode = System.Net.HttpStatusCode.InternalServerError
};
}
}
}
다음을 사용하여 다음과 같은 데모를 트리거하는 코드 그것:
[DivideByZeroExceptionFilter]
public void Delete(int id)
{
// causes the DivideByZeroExceptionFilter attribute to be triggered:
throw new DivideByZeroException();
}
지금 우리가 알고있는 어떻게 사용되는,우리는 주로 관심이 있에서 구현됩니다.다음 코드에서입니다.NET Framework.그것을 사용하여 인터페이스 IExceptionFilter
내부적으로는 계약:
namespace System.Web.Http.Filters
{
public interface IExceptionFilter : IFilter
{
// Executes an asynchronous exception filter.
// Returns: An asynchronous exception filter.
Task ExecuteExceptionFilterAsync(
HttpActionExecutedContext actionExecutedContext,
CancellationToken cancellationToken);
}
}
이 ExceptionFilterAttribute
자체의 정의는 다음과 같습니다.
namespace System.Web.Http.Filters
{
// Represents the attributes for the exception filter.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
Inherited = true, AllowMultiple = true)]
public abstract class ExceptionFilterAttribute : FilterAttribute,
IExceptionFilter, IFilter
{
// Raises the exception event.
// actionExecutedContext: The context for the action.</param>
public virtual void OnException(
HttpActionExecutedContext actionExecutedContext)
{
}
// Asynchronously executes the exception filter.
// Returns: The result of the execution.
Task IExceptionFilter.ExecuteExceptionFilterAsync(
HttpActionExecutedContext actionExecutedContext,
CancellationToken cancellationToken)
{
if (actionExecutedContext == null)
{
throw Error.ArgumentNull("actionExecutedContext");
}
this.OnException(actionExecutedContext);
return TaskHelpers.Completed();
}
}
}
안 ExecuteExceptionFilterAsync
, 방법 OnException
라고 합니다.당신이 있기 때문에 재정의 그림과 같이 이전에 오류 처리할 수 있습에 의해 자신의 코드입니다.
거기에는 또한 상업적인 제품으로 사용할 수 있에서 언급 OwenP 의 답변, PostSharp, 할 수 있는 그렇게 쉽습니다. 기 예입니다 어떻게 당신이 할 수 있는 PostSharp.참고가 있는 익스프레스 버전 사용할 수 있는 무료로 사용할 수 있습도에 대한 상업 프로젝트입니다.
PostSharp 예 (링크를 참조 위에 설명):
public class CustomerService
{
[RetryOnException(MaxRetries = 5)]
public void Save(Customer customer)
{
// Database or web-service call.
}
}
여기에 속성을 지정하는 Save
방법은 최대 5 배까지는 경우는 예외가 발생합니다.다음 코드를 정의 이용 속성:
[PSerializable]
public class RetryOnExceptionAttribute : MethodInterceptionAspect
{
public RetryOnExceptionAttribute()
{
this.MaxRetries = 3;
}
public int MaxRetries { get; set; }
public override void OnInvoke(MethodInterceptionArgs args)
{
int retriesCounter = 0;
while (true)
{
try
{
args.Proceed();
return;
}
catch (Exception e)
{
retriesCounter++;
if (retriesCounter > this.MaxRetries) throw;
Console.WriteLine(
"Exception during attempt {0} of calling method {1}.{2}: {3}",
retriesCounter, args.Method.DeclaringType, args.Method.Name, e.Message);
}
}
}
}
일종의 측면 지향 프레임 워크가 필요합니다. PostSharp는 Will과 같이 할 것입니다 윈저.
기본적으로 그들은 당신의 객체를 서브 클래스 하고이 방법을 무시합니다 ...
그런 다음 :
//proxy
public override void DoSomeStuff()
{
if(MethodHasTriggerAttribute)
Trigger();
_innerClass.DoSomeStuff();
}
물론이 모든 것이 당신에게 숨겨져 있습니다. Windsor에게 유형을 물어 보는 것만 큼, 그것은 당신을 위해 프록시를 할 것입니다. 이 속성은 윈저에서 생각하는 (맞춤형) 시설이됩니다.
ContextBoundObject 및 iMessagesInk를 사용할 수 있습니다. 보다 http://msdn.microsoft.com/nb-no/magazine/cc301356(en-us).aspx
이 접근법은 직접 방법 호출과 비교하여 심각한 성능 영향을 미칩니다.
나는 속성만으로 그것을 할 수있는 방법이 없다고 생각하지만 프록시 클래스 그리고 반성 당신은 당신이 방법에 귀속 된 클래스의 인스턴스를 가로 채는 것을 알고있는 수업을 가질 수 있습니다.
그런 다음 프록시 클래스는 귀속 된 메소드가 호출 될 때마다 이벤트를 트리거 할 수 있습니다.
속성은 정보를 제공하고 메타 데이터입니다. 나는 이것을 해제하는 방법을 모른다. 누군가가 할 수도있다.
.NET의 부분 방법을 볼 수있어 가벼운 이벤트 처리를 수행 할 수 있습니다. 후크를 제공하고 다른 사람이 구현을 처리하도록합니다. 메소드가 구현되지 않으면 컴파일러가 무시합니다.
가난한 사람의 해결책을 살펴볼 수 있습니다 : 데코레이터 패턴을 참조하십시오.