2013-06-13 2 views
7

C# 단일 속성으로 가로 채기를 사용하고 XML (app.config와 같은) 개체 등록 코드를 유지하는 방법이 있습니까? 그렇다면 코드를 제게 제공 할 수 있습니까? 그런 등록은 어떻게 보입니까? 나는 많은 해결책을 찾았지만이 문제에 대한 해결책을 찾지 못했습니다.C# unity interception by 속성

답변

14

사용자 지정 속성을 사용하여 가로 챌 방법을 나타내는 것으로 가정합니다. 정책 삽입을 사용하여 XML 구성을 사용하여 가로 챌 수 있습니다.

먼저, 사용자 정의 속성을 정의 할 수 있습니다 :

[AttributeUsage(AttributeTargets.Method)] 
public class MyInterceptionAttribute : Attribute 
{ 
} 

다음 우리는 약간의 차단 작업을 수행 할 수있는 ICallHandler을 만들 수 있습니다. 이 구현은 직전 Console.WriteLine을 할 것입니다 및 방법 후 :

public interface IMyClass 
{ 
    void Do(); 
    void DoAgain(); 
} 

public class MyClass : IMyClass 
{ 
    [MyInterception] 
    public void Do() 
    { 
     Console.WriteLine("Do!"); 
    } 

    public void DoAgain() 
    { 
     Console.WriteLine("Do Again!"); 
    } 
} 

공지 사항 I는 사용자 지정 특성을 적용한 :

public class MyLoggingCallHandler : ICallHandler 
{ 
    IMethodReturn ICallHandler.Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) 
    { 
     Console.WriteLine("Invoking " + input.MethodBase.Name); 
     IMethodReturn result = getNext()(input, getNext); 
     Console.WriteLine("Done Invoke"); 
     return result; 
    } 

    int ICallHandler.Order { get; set; } 
} 

다음의 우리가 어떤 인터페이스와 구현이 있다고 가정하자 , MyInterception을 Do 메소드에만 적용하고 DoAgain 메소드에는 적용하지 않습니다. 우리는 Do 메소드에 대한 모든 호출을 인터셉트합니다. 우리는 또한에 사용자 지정 특성의 문자열 표현을 변환하는 형식 변환기를 필요

<?xml version="1.0"?> 
<configuration> 
    <configSections> 
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/> 
    </configSections> 
    <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> 
    <namespace name="UnityCallHandlerConfig" /> 
    <assembly name="UnityCallHandlerConfig" /> 
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/> 
    <container> 
     <extension type="Interception"/> 
     <interception> 
     <policy name="Policy"> 
      <matchingRule name="Match" type="Microsoft.Practices.Unity.InterceptionExtension.CustomAttributeMatchingRule, Microsoft.Practices.Unity.Interception"> 
      <constructor> 
       <param name="attributeType" value="UnityCallHandlerConfig.MyInterceptionAttribute, UnityCallHandlerConfig" typeConverter="AssemblyQualifiedTypeNameConverter" /> 
       <param name="inherited"> 
       <value value="false"/> 
       </param> 
      </constructor> 
      </matchingRule> 
      <callHandler name="MyLogging" type="MyLoggingCallHandler"> 
      <lifetime type="singleton"/> 
      </callHandler> 
     </policy> 
     </interception> 
     <register type="IMyClass" mapTo="MyClass"> 
     <interceptor type="InterfaceInterceptor"/> 
     <interceptionBehavior type="PolicyInjectionBehavior"/> 
     </register> 
    </container> 
    </unity> 

    <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/> 
    </startup> 
</configuration> 

:

다음으로 우리는 정책을 정의하는 일치 규칙을 구성하고 인터셉터와 함께 유형을 등록하는 구성을 만들 올바른 유형 :

public class AssemblyQualifiedTypeNameConverter : ConfigurationConverterBase 
{ 
    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) 
    { 
     if (value != null) 
     { 
      Type typeValue = value as Type; 
      if (typeValue == null) 
      { 
       throw new ArgumentException("Cannot convert type", typeof(Type).Name); 
      } 

      if (typeValue != null) return (typeValue).AssemblyQualifiedName; 
     } 
     return null; 
    } 

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) 
    { 
     string stringValue = (string)value; 
     if (!string.IsNullOrEmpty(stringValue)) 
     { 
      Type result = Type.GetType(stringValue, false); 
      if (result == null) 
      { 
       throw new ArgumentException("Invalid type", "value"); 
      } 

      return result; 
     } 
     return null; 
    } 
} 

우리는 일단 우리가 구성 컨테이너를 만들고로드 할 수 있습니다 설정 모든 :

var container = new UnityContainer().LoadConfiguration(); 

var myClass = container.Resolve<IMyClass>(); 
myClass.Do(); 
myClass.DoAgain(); 

출력 될 것이다

Invoking Do 
Do! 
Done Invoke 
Do Again! 

번째는 아니지만 첫 번째 방법은 인터셉트 보여주는.

+0

도움을 주셔서 감사합니다. –

+2

@Tuzo, 어떻게 구성이 C# 코드로 보입니까? 코드에서 완료되면 여전히 'AssemblyQualifiedTypeNameConverter'이 필요합니까? –