2013-06-13 6 views
7

C#の属性でインターセプトを使用し、オブジェクト登録コードをXMLファイル(app.configなど)に保存する方法はありますか?はいの場合は、私にコードを提供できますか?そのような登録はどのように見えますか?私は多くの回避策を講じましたが、この問題の解決策を見つけることはできませんでした。C#unity interception by attribute

答えて

14

カスタム属性を使用して、どのメソッドを傍受するかを指定しているとします。ポリシー設定を使用して、XML設定を使用してインターセプトを達成できます。

まずは、カスタム属性を定義してみましょう:

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

次の我々はいくつかの傍受の仕事をするICallHandlerを作成することができます。この実装は、単にメソッドの前と後にConsole.WriteLineをを行います。

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

次は、我々はいくつかのインタフェースと実装を持っていると仮定しましょう:私はカスタム属性を適用した

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

お知らせ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> 

我々はまた、にカスタム属性の文字列表現を変換する型コンバータを必要とします適切なタイプ:

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

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

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

我々は、コンテナを作成し、設定を読み込むことができます設定することすべてを持っていたら、

出力は次のようになります。第二はないが最初の方法が傍受されたことを示す

Invoking Do 
Do! 
Done Invoke 
Do Again! 

+0

ありがとうございました! –

+2

@Tuzo、C#コードの設定はどうでしたか?あなたがまだ 'AssemblyQualifiedTypeNameConverter'がコードで終わっていれば必要ですか? –