<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>EntLib</title><link>http://blogs.wankuma.com/nakamura/category/1965.aspx</link><description>Enterprise Library を扱います。</description><managingEditor>なかむら</managingEditor><dc:language>ja-JP</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>なかむら</dc:creator><title>Unity を使って WCF で AOP する</title><link>http://blogs.wankuma.com/nakamura/archive/2009/11/12/182930.aspx</link><pubDate>Thu, 12 Nov 2009 07:06:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakamura/archive/2009/11/12/182930.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakamura/comments/182930.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakamura/archive/2009/11/12/182930.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakamura/comments/commentRss/182930.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakamura/services/trackbacks/182930.aspx</trackback:ping><description>&lt;h4&gt;はじめに&lt;/h4&gt;
&lt;p&gt;
先日、Unity で AOP を使う方法を紹介しました。
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;a href="http://d.hatena.ne.jp/griefworker/20091112/wcf_unity_aop" target="_blank"&gt;続きを読む&lt;/a&gt;
&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nakamura/aggbug/182930.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>なかむら</dc:creator><title>Unity を使って AOP</title><link>http://blogs.wankuma.com/nakamura/archive/2009/11/10/182869.aspx</link><pubDate>Tue, 10 Nov 2009 06:28:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakamura/archive/2009/11/10/182869.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakamura/comments/182869.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakamura/archive/2009/11/10/182869.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakamura/comments/commentRss/182869.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakamura/services/trackbacks/182869.aspx</trackback:ping><description>&lt;p&gt;
かな～り前に、Enterprise Library の Policy Injection Application Block の機能が Unity に統合された、という記事を書きました。
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;a href="http://d.hatena.ne.jp/griefworker/20091110/unity_di_aop" target="_blank"&gt;続きを読む&lt;/a&gt;
&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nakamura/aggbug/182869.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>なかむら</dc:creator><title>EntLib4.1 での PIAB 仕様変更 (2)</title><link>http://blogs.wankuma.com/nakamura/archive/2008/12/04/162644.aspx</link><pubDate>Thu, 04 Dec 2008 09:46:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakamura/archive/2008/12/04/162644.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakamura/comments/162644.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakamura/archive/2008/12/04/162644.aspx#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakamura/comments/commentRss/162644.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakamura/services/trackbacks/162644.aspx</trackback:ping><description>&lt;h4&gt;はじめに&lt;/h4&gt;
&lt;p&gt;
&lt;a href="http://blogs.wankuma.com/nakamura/archive/2008/12/02/162461.aspx"&gt;先日&lt;/a&gt;に引き続き
 Policy Injection Application Block (以下 PIAB) の変更点を調べました。
&lt;/p&gt;

&lt;h4&gt;変更点&lt;/h4&gt;
&lt;p&gt;
EntLib4.1 では、メソッドのインターセプトを Unity がやってくれるようになりました。
PIAB は Unity の機能を利用するだけです。
&lt;/p&gt;

&lt;h4&gt;Unity を使ったメソッドのインターセプト方法&lt;/h4&gt;
&lt;p&gt;
Microsoft.Practices.Unity.Interception を参照に追加し、例えば下記のようなコードを書けばＯＫです。
&lt;/p&gt;
&lt;pre name="code" class="c#"&gt;
// DI コンテナを生成する。
IUnityContainer container = new UnityContainer();

// DI コンテナのインスタンス生成パイプラインを拡張する。
// インスタンスをラップしてメソッドをインターセプト可能にする処理が追加される。
container.AddNewExtension&amp;lt;Interception&amp;gt;();

// DI コンテナから取得するインスタンスをインターセプトする方法を指定。
container.Configure&amp;lt;Interception&amp;gt;()
         .SetInterceptorFor&amp;lt;IAnimal&amp;gt;(new TransparentProxyInterceptor());

// 型を登録する。
container.RegisterType&amp;lt;IAnimal, Wankuma&amp;gt;("Wankuma");

// コンテナから取得した animal オブジェクトの、
// Cry メソッドはインターセプトされる。
var animal = container.Resolve&amp;lt;IAnimal&amp;gt;("Wankuma");
animal.Cry();
&lt;/pre&gt;

&lt;h4&gt;最後に&lt;/h4&gt;
&lt;p&gt;
Unity だけでアスペクト指向プログラミングが可能になっています。
PIAB の存在意義が・・・(;^_^A
&lt;/p&gt;
&lt;img src ="http://blogs.wankuma.com/nakamura/aggbug/162644.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>なかむら</dc:creator><title>EntLib4.1 での PIAB 仕様変更</title><link>http://blogs.wankuma.com/nakamura/archive/2008/12/02/162461.aspx</link><pubDate>Tue, 02 Dec 2008 09:13:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakamura/archive/2008/12/02/162461.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakamura/comments/162461.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakamura/archive/2008/12/02/162461.aspx#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakamura/comments/commentRss/162461.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakamura/services/trackbacks/162461.aspx</trackback:ping><description>&lt;h4&gt;一部のクラスやインタフェースが無くなっていました&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Microsoft.Practices.EnterpriseLibrary.PolicyInjection.ICallHandler&lt;/li&gt;
&lt;li&gt;Microsoft.Practices.EnterpriseLibrary.PolicyInjection.IMethodInvocation&lt;/li&gt;
&lt;li&gt;Microsoft.Practices.EnterpriseLibrary.PolicyInjection.IMethodReturn&lt;/li&gt;
&lt;li&gt;Microsoft.Practices.EnterpriseLibrary.PolicyInjection.GetNextHandlerDelegate&lt;/li&gt;
&lt;li&gt;Microsoft.Practices.EnterpriseLibrary.PolicyInjection.HandlerAttribute&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;でも代わりが用意されています&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Microsoft.Practices.Unity.InterceptionExtension.ICallHandler&lt;/li&gt;
&lt;li&gt;Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation&lt;/li&gt;
&lt;li&gt;Microsoft.Practices.Unity.InterceptionExtension.IMethodReturn&lt;/li&gt;
&lt;li&gt;Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate&lt;/li&gt;
&lt;li&gt;Microsoft.Practices.Unity.InterceptionExtension.HandlerAttribute&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;HandlerAttributeのインタフェースも変更されていました&lt;/h4&gt;
&lt;p&gt;
CreateHandler メソッドが引数を受け取るようになっています。
&lt;/p&gt;
&lt;pre name="code" class="c#"&gt;
public class EventLogCallHandlerAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new EventLogCallHandler();
    }
}
&lt;/pre&gt;
&lt;p&gt;
このコードは「&lt;a href="http://blogs.wankuma.com/nakamura/archive/2008/11/18/161633.aspx"&gt;PIABで属性を使ってインターセプト対象メソッドを指定する&lt;/a&gt;」で作成した
 EvetnLogCallHandler を EntLib4.1 に対応させたものです。
&lt;/p&gt;

&lt;h4&gt;まだまだ変更がありそう&lt;/h4&gt;
&lt;p&gt;
もっと調べてみます。
&lt;/p&gt;
&lt;img src ="http://blogs.wankuma.com/nakamura/aggbug/162461.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>なかむら</dc:creator><title>Unity の LifetimeManager</title><link>http://blogs.wankuma.com/nakamura/archive/2008/12/01/162406.aspx</link><pubDate>Mon, 01 Dec 2008 09:33:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakamura/archive/2008/12/01/162406.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakamura/comments/162406.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakamura/archive/2008/12/01/162406.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakamura/comments/commentRss/162406.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakamura/services/trackbacks/162406.aspx</trackback:ping><description>&lt;h4&gt;UnityContainer に型を登録するとき&lt;/h4&gt;
&lt;pre name="code" class="c#"&gt;
container.RegisterType&amp;lt;IAnimal, Wankuma&amp;gt;(lifetimeManager);
&lt;/pre&gt;
&lt;p&gt;
という風に LifetimeManager も一緒に指定できます。
UnityContainer を使って生成したインスタンスの生存期間は、
一緒に登録した LifetimeManager が管理してます。
&lt;/p&gt;

&lt;h4&gt;Unity が提供する LifetimeManager&lt;/h4&gt;
&lt;p&gt;
表にしてみました。
&lt;/p&gt;
&lt;table border="1" cellspacing="0"&gt;
  &lt;tr&gt;
    &lt;th&gt;種類&lt;/th&gt;
    &lt;th&gt;説明&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;ContainerControlledLifetimeManager&lt;/td&gt;
    &lt;td&gt;LifetimeManagerが破棄されるときにインスタンスも破棄します。それまで１つのインスタンスを使い回します。&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;ExternallyControlledLifetimeManager&lt;/td&gt;
    &lt;td&gt;インスタンスの管理に WeakReference を使用しています。&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;PerThreadLifetimeManager&lt;/td&gt;
    &lt;td&gt;スレッド内で１つのインスタンスを使い回します。&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;TransientLifetimeManager&lt;/td&gt;
    &lt;td&gt;毎回新しいインスタンスを生成します。&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;h4&gt;例えば&lt;/h4&gt;
&lt;p&gt;
毎回新しいインスタンスを生成して欲しい場合、
TransientLifetimeManager を指定すればいいですね。
&lt;/p&gt;
&lt;img src ="http://blogs.wankuma.com/nakamura/aggbug/162406.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>なかむら</dc:creator><title>Unity と PIAB を連携させる</title><link>http://blogs.wankuma.com/nakamura/archive/2008/11/21/161824.aspx</link><pubDate>Fri, 21 Nov 2008 09:54:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakamura/archive/2008/11/21/161824.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakamura/comments/161824.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakamura/archive/2008/11/21/161824.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakamura/comments/commentRss/161824.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakamura/services/trackbacks/161824.aspx</trackback:ping><description>&lt;h4&gt;はじめに&lt;/h4&gt;
&lt;p&gt;
Unity と Policy Injection Application Block (以下 PIAB) と連携させてみました。
&lt;/p&gt;

&lt;h4&gt;カスタム Callhandler とカスタム HandlerAttribute&lt;/h4&gt;
&lt;pre name="code" class="c#"&gt;
[ConfigurationElementType(typeof(CustomCallHandlerData))]
public class EventLogCallHandler : ICallHandler
{
    public int Order { get; set; }

    public EventLogCallHandler(NameValueCollection attributes)
    {
        // このコンストラクタは必須みたい
    }

    private const string SOURCE = "PIABSample";

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        // メソッド呼び出し前にログを出力
        EventLog.WriteEntry(SOURCE,
            string.Format("{0} メソッドを呼び出します。", input.MethodBase.Name),
            EventLogEntryType.Information);

        // メソッド呼び出し
        IMethodReturn result = getNext()(input, getNext);

        // メソッド呼び出し後にログを出力
        if (result.Exception != null)
        {
            // 例外が発生したとき
            EventLog.WriteEntry(SOURCE,
            string.Format("{0} メソッド呼び出しで例外が発生しました。", input.MethodBase.Name),
            EventLogEntryType.Error);
        }
        else
        {
            EventLog.WriteEntry(SOURCE,
            string.Format("{0} メソッドを呼び出しました。", input.MethodBase.Name),
            EventLogEntryType.Information);
        }

        return result;
    }
}

public class EventLogCallHandlerAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler()
    {
        return new EventLogCallHandler();
    }
}
&lt;/pre&gt;
&lt;p&gt;
『&lt;a href="http://blogs.wankuma.com/nakamura/archive/2008/11/18/161633.aspx"&gt;PIAB で属性を使ってインターセプト対象メソッドを指定する&lt;/a&gt;』のエントリで作成したものを流用します。
&lt;/p&gt;

&lt;h4&gt;DI で使用するインタフェースとクラスを用意&lt;/h4&gt;
&lt;pre name="code" class="c#"&gt;
public interface IAnimal
{
    // Cry メソッド呼び出し時にイベントログを出力する
    [EventLogCallHandler]
    void Cry();
}

public class Wankuma : IAnimal
{
    public void Cry()
    {
        Console.WriteLine("クマ～");
    }
}

public class Person
{
    [Dependency]
    public IAnimal Pet { get; set; }

    public void CallPet()
    {
        Pet.Cry();
    }
}
&lt;/pre&gt;
&lt;p&gt;
毎度おなじみのインタフェースとクラスです^^;
&lt;/p&gt;

&lt;h4&gt;PIAB と Unity を連携させるために UnityContainerExtension を作成&lt;/h4&gt;
&lt;p&gt;
ここからが本番。
&lt;/p&gt;
&lt;pre name="code" class="c#"&gt;
public class EventLogExtension : UnityContainerExtension
{
    protected override void Initialize()
    {
        // ここで登録した PolicyIjectionPolicy は次に登録する
        // PolicyInjectionStrategy で使われます。
        Context.Policies.SetDefault&amp;lt;IPolicyInjectionPolicy&amp;gt;(new PolicyInjectionPolicy(true));
        
        // Unity がインスタンスを生成するパイプラインの PreCreation ステージで、
        // PolicyInjectionStrategy の処理が実行されるように登録します。
        Context.Strategies.AddNew&amp;lt;PolicyInjectionStrategy&amp;gt;(UnityBuildStage.PreCreation);
    }
}
&lt;/pre&gt;
&lt;p&gt;
PolicyInjectionStrategy は登録した PolicyInjectionPolicy を使って、Unity が生成したインスタンスに PIAB のポリシーを適用します。つまり RealProxy の派生クラスでラップする。この辺りは『&lt;a href="http://blogs.wankuma.com/nakamura/archive/2008/11/20/161776.aspx"&gt;PIABの中身を見てみた&lt;/a&gt;』のエントリを見て下さい。
&lt;/p&gt;
&lt;p&gt;
Strategies や Policies がどう利用されるのかについては、後でエントリにする予定です。
&lt;/p&gt;

&lt;h4&gt;作成した UnityContainerExtension を使ったコードに修正&lt;/h4&gt;
&lt;pre name="code" class="c#"&gt;
static void Main(string[] args)
{
    // DI コンテナ取得
    UnityContainer container = new UnityContainer();

    // DI コンテナを拡張
    container.AddNewExtension&amp;lt;EventLogExtension&amp;gt;();

    // 型を登録
    container.RegisterType&amp;lt;IAnimal, Wankuma&amp;gt;();

    // インスタンスを取得
    Person person = container.Resolve&amp;lt;Person&amp;gt;();

    // ペットを呼び出す
    person.CallPet();

    Console.ReadLine();
}
&lt;/pre&gt;
&lt;p&gt;
作成した EventLogExtension を使って、UnityContainer を拡張しています。
&lt;/p&gt;
&lt;p&gt;
このコードを実行すると、CallPet メソッド内で Cry メソッドが呼ばれる前後にイベントログが出力されます。
&lt;/p&gt;

&lt;h4&gt;まとめ&lt;/h4&gt;
&lt;p&gt;
Unity と PIAB の連携は、UnityContainer のインスタンス生成処理のパイプラインに、ポリシーを適用する処理を組み込むための UnityContainerExtension を作成することで実現可能です。
&lt;/p&gt;
&lt;img src ="http://blogs.wankuma.com/nakamura/aggbug/161824.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>なかむら</dc:creator><title>PIAB の中身を見てみた</title><link>http://blogs.wankuma.com/nakamura/archive/2008/11/20/161776.aspx</link><pubDate>Thu, 20 Nov 2008 11:30:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakamura/archive/2008/11/20/161776.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakamura/comments/161776.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakamura/archive/2008/11/20/161776.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakamura/comments/commentRss/161776.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakamura/services/trackbacks/161776.aspx</trackback:ping><description>&lt;h4&gt;はじめに&lt;/h4&gt;
&lt;p&gt;
「使っているものの仕組みをしれ！」みたいな教えを以前受けた気がするので、
Policy Injection Application Block のソースコードを読んでみました。
&lt;p&gt;
&lt;p&gt;
先日のエントリ『&lt;a href="http://blogs.wankuma.com/nakamura/archive/2008/11/18/161633.aspx"&gt;PIABで属性を使ってインターセプト対象メソッドを指定する&lt;/a&gt;』で作成したサンプルの
&lt;/p&gt;
&lt;pre name="code" class="c#"&gt;
var animal = PolicyInjection.Create&amp;lt;Wankuma&amp;gt;();
&lt;/pre&gt;
&lt;p&gt;
の部分で何をやっているのかを、ざっと追っていきます。
&lt;/p&gt;


&lt;h4&gt;PolicyInjection クラス&lt;/h4&gt;

&lt;h5&gt;Create メソッド&lt;/h5&gt;
&lt;pre name="code" class="c#"&gt;
public static class PolicyInjection
{
    private static volatile PolicyInjector defaultPolicyInjector;
    private static readonly object singletonLock = new object();

    public static TObject Create&amp;lt;TObject&amp;gt;(params object[] args)
    {
        return DefaultPolicyInjector.Create&amp;lt;TObject&amp;gt;(args);
    }    
&lt;/pre&gt;
&lt;p&gt;
デフォルトの PolicyInjector を取得して、Create メソッドを呼んでいます。
&lt;/p&gt;

&lt;h5&gt;DefaultPolicyInjector プロパティ&lt;/h5&gt;
&lt;pre name="code" class="c#"&gt;
private static PolicyInjector DefaultPolicyInjector
{
    get
    {
        if( defaultPolicyInjector == null)
        {
            lock(singletonLock)
            {
                if(defaultPolicyInjector == null)
                {
                    IConfigurationSource configurationSource =
                        ConfigurationSourceFactory.Create();
                    defaultPolicyInjector = GetInjectorFromConfig(configurationSource);
                }
            }
        }
        return defaultPolicyInjector;
    }
}

private static PolicyInjector GetInjectorFromConfig(IConfigurationSource configurationSource)
{
    PolicyInjectorFactory injectorFactory = new PolicyInjectorFactory(configurationSource);
    return injectorFactory.Create();
}
&lt;/pre&gt;
&lt;p&gt;
構成ファイルの内容を PolicyInjectorFactory に渡し、Create メソッドで PolicyInjector を生成してます。
初めてこのプロパティを使うときに、1回だけ生成されるみたいですね。
&lt;/p&gt;


&lt;h4&gt;PolicyInjectorFactory クラス&lt;/h4&gt;

&lt;h5&gt;Create メソッド&lt;/h5&gt;
&lt;pre name="code" class="c#"&gt;
public class PolicyInjectorFactory
{
    public PolicyInjector Create()
    {
        return EnterpriseLibraryFactory.BuildUp&amp;lt;PolicyInjector&amp;gt;(configurationSource);
    }
&lt;/pre&gt;
&lt;p&gt;
EnterpriseLibraryFactory は内部で ObjectBuilder を使って PolicyInjector を生成しています。
&lt;/p&gt;


&lt;h4&gt;PolicyInjector クラス&lt;/h4&gt;

&lt;h5&gt;Create メソッド&lt;/h5&gt;
&lt;pre name="code" class="c#"&gt;
[CustomFactory(typeof(PolicyInjectorCustomFactory))]
public abstract class PolicyInjector
{
    public object Create(Type typeToCreate, Type typeToReturn, params object[] args)
    {
        // 構成ファイルや属性をチェックして、型に適用するポリシーを取り出す
        PolicySet policiesForThisType = policies.GetPoliciesFor(typeToCreate);

        // インターセプト可能かどうかチェックする。
        // インターセプト出来ない場合は ArgumentException を発生させる。
        EnsureTypeIsInterceptable(typeToReturn, policiesForThisType);

        return DoCreate(typeToCreate, typeToReturn, policiesForThisType, args);
    }
&lt;/pre&gt;
&lt;p&gt;
インターセプト可能かどうかの判断基準は「ポリシーが指定されているか」「MarshalByRefObject を継承しているか」など。PolicyInjector の実装によって異なります。
あと、実際にインスタンスを生成しているのは DoCreate メソッド。
&lt;/p&gt;

&lt;h5&gt;DoCreate メソッド&lt;/h5&gt;
&lt;pre name="code" class="c#"&gt;
protected virtual object DoCreate(Type typeToCreate, Type typeToReturn, PolicySet policiesForThisType, object[] arguments)
{
    object target = Activator.CreateInstance(typeToCreate, arguments);
    return DoWrap(target, typeToReturn, policiesForThisType);
}
&lt;/pre&gt;
&lt;p&gt;
リフレクションを使ってインスタンスを生成したあと、DoWrap メソッド呼んでいますね。
DoWrap メソッドは abstract なので、今回は RemotingPolicyInjector クラスの DoWrap を見てみる。
&lt;/p&gt;

&lt;h4&gt;RemotingPolicyInjector クラス&lt;/h4&gt;

&lt;h5&gt;DoWrap メソッド&lt;/h5&gt;
&lt;pre name="code" class="c#"&gt;
[ConfigurationElementType(typeof(RemotingInjectorData))]
public class RemotingPolicyInjector : PolicyInjector
{
    protected override object DoWrap(object instance, Type typeToReturn, PolicySet policiesForThisType)
    {
        if (PolicyRequiresInterception(policiesForThisType))
        {
            // instance が既に RealProxy でラップされている場合は、ラップを解いて渡す。
            // ラップされていない場合はそのまま渡す。
            InterceptingRealProxy proxy =
                new InterceptingRealProxy(UnwrapTarget(instance), typeToReturn, policiesForThisType);
            return proxy.GetTransparentProxy();
        }
        return instance;
    }
&lt;/pre&gt;
&lt;p&gt;
InterceptingReadProxy は RealProxy を継承したクラスです。
透過プロキシを返しているのかぁ。
&lt;/p&gt;


&lt;h4&gt;InterceptingReadProxy クラス&lt;/h4&gt;

&lt;h5&gt;コンストラクタ&lt;/h5&gt;
&lt;pre name="code" class="c#"&gt;
public InterceptingRealProxy(object target, Type classToProxy, PolicySet policies)
    : base(classToProxy)
{
    this.target = target;
    this.typeName = target.GetType().FullName;
    Type targetType = target.GetType();

    memberHandlers = new Dictionary&amp;lt;MethodBase, HandlerPipeline&amp;gt;();

　　// クラスの情報から CallHandler を取得して memberHandlers に追加します
    AddHandlersForType(targetType, policies);

    // ここではベースクラスから
    Type baseTypeIter = targetType.BaseType;
    while (baseTypeIter != null &amp;&amp; baseTypeIter != typeof(object))
    {
        AddHandlersForType(baseTypeIter, policies);
        baseTypeIter = baseTypeIter.BaseType;
    }

    foreach (Type inter in targetType.GetInterfaces())
    {
        // クラスとインタフェースをマッピングしたあと、
        // クラスのメソッド情報をもとに取得した CallHandler を
        // インタフェースのメソッド用の CallHandler として再登録している
        AddHandlersForInterface(targetType, inter);
    }        
}
&lt;/pre&gt;
&lt;p&gt;
コンストラクタ内でクラスの情報をもとに CallHandler を取得して、メンバに保存しています。
&lt;/p&gt;
&lt;p&gt;
Create の流れはここで終了。でもせっかくなので、メソッドが実際にインターセプトされる処理も見てみます。
&lt;/p&gt;

&lt;h5&gt;Invoke メソッド&lt;/h5&gt;
&lt;pre name="code" class="c#"&gt;
public class InterceptingRealProxy : RealProxy, IRemotingTypeInfo
{
    public override IMessage Invoke(IMessage msg)
    {
        IMethodCallMessage callMessage = (IMethodCallMessage)msg;

        // メソッドをインターセプトして実行する CallHandler を取得する
        HandlerPipeline pipeline;
        if (memberHandlers.ContainsKey(callMessage.MethodBase))
        {
            pipeline = memberHandlers[callMessage.MethodBase];
        }
        else
        {
            pipeline = new HandlerPipeline();
        }

        RemotingMethodInvocation invocation = new RemotingMethodInvocation(callMessage, target);
        IMethodReturn result =
            pipeline.Invoke(
                invocation,
                delegate(IMethodInvocation input, GetNextHandlerDelegate getNext)
                {
                    try
                    {
                        // インターセプト対象のメソッドを実行
                        object returnValue = callMessage.MethodBase.Invoke(target, invocation.Arguments);
                        return input.CreateMethodReturn(returnValue, invocation.Arguments);
                    }
                    catch (TargetInvocationException ex)
                    {
                        // The outer exception will always be a reflection exception; we want the inner, which is
                        // the underlying exception.
                        return input.CreateExceptionMethodReturn(ex.InnerException);
                    }
                });
        return ((RemotingMethodReturn)result).ToMethodReturnMessage();
    }
&lt;/pre&gt;
&lt;p&gt;
インターセプト対象メソッドの情報をもとに HandlerPipeline を取得して、
その Invoke メソッドを呼び出しているのか。
インターセプトされたメソッドは、リフレクション(MethodBase.Invoke)で呼び出しています。
&lt;/p&gt;


&lt;h4&gt;HandlerPipeline クラス&lt;/h4&gt;

&lt;h5&gt;Invoke メソッド&lt;/h5&gt;
&lt;pre name="code" class="c#"&gt;
public class HandlerPipeline
{
    private List&amp;lt;ICallHandler&amp;gt; handlers;

    public IMethodReturn Invoke(IMethodInvocation input, InvokeHandlerDelegate target)
    {
        if( handlers.Count == 0 )
        {
            return target(input, null);
        }

        int handlerIndex = 0;

        // メソッドをインターセプトして実行する処理を、連鎖して呼び出す
        IMethodReturn result = handlers[0].Invoke(input, delegate
                                  {
                                      ++handlerIndex;
                                      if(handlerIndex &amp;lt; handlers.Count)
                                      {
                                          return handlers[handlerIndex].Invoke;
                                      }
                                      else
                                      {
                                          return target;
                                      }
                                  });
        return result;
    }
&lt;/pre&gt;
&lt;p&gt;
構成ファイルなどで指定した CallHander がこのクラスに登録されています。
先に登録されているハンドラを呼び出して、最後にインターセプト対象のメソッドが呼ばれる・・・と。
&lt;/p&gt;


&lt;h4&gt;最後に&lt;/h4&gt;
&lt;p&gt;
PIAB では RealProxy を使って AOP を実現しているのか！
&lt;/p&gt;
&lt;img src ="http://blogs.wankuma.com/nakamura/aggbug/161776.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>なかむら</dc:creator><title>PIABで属性を使ってインターセプト対象メソッドを指定する</title><link>http://blogs.wankuma.com/nakamura/archive/2008/11/18/161633.aspx</link><pubDate>Tue, 18 Nov 2008 16:47:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakamura/archive/2008/11/18/161633.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakamura/comments/161633.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakamura/archive/2008/11/18/161633.aspx#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakamura/comments/commentRss/161633.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakamura/services/trackbacks/161633.aspx</trackback:ping><description>&lt;h4&gt;はじめに&lt;/h4&gt;
&lt;p&gt;
&lt;a href="http://blogs.wankuma.com/nakamura/archive/2008/11/12/161026.aspx"&gt;以前書いた Policy Injection Application Block のサンプル&lt;/a&gt;は
構成ファイルでインターセプトするメソッドを指定していました。
インターセプトするメソッドは属性でも指定可能なので、
今回はその方法を試してみました。
&lt;/p&gt;

&lt;h4&gt;カスタム CallHandler を作成&lt;/h4&gt;
&lt;pre name="code" class="c#"&gt;
[ConfigurationElementType(typeof(CustomCallHandlerData))]
public class EventLogCallHandler : ICallHandler
{
    public int Order { get; set; }

    public EventLogCallHandler(NameValueCollection attributes)
    {
        // このコンストラクタは必須みたい
    }

    private const string SOURCE = "PIABSample";

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        // メソッド呼び出し前にログを出力
        EventLog.WriteEntry(SOURCE,
            string.Format("{0} メソッドを呼び出します。", input.MethodBase.Name),
            EventLogEntryType.Information);

        // メソッド呼び出し
        IMethodReturn result = getNext()(input, getNext);

        // メソッド呼び出し後にログを出力
        if (result.Exception != null)
        {
            // 例外が発生したとき
            EventLog.WriteEntry(SOURCE,
            string.Format("{0} メソッド呼び出しで例外が発生しました。", input.MethodBase.Name),
            EventLogEntryType.Error);
        }
        else
        {
            EventLog.WriteEntry(SOURCE,
            string.Format("{0} メソッドを呼び出しました。", input.MethodBase.Name),
            EventLogEntryType.Information);
        }

        return result;
    }
}
&lt;/pre&gt;
&lt;p&gt;
&lt;a href="http://blogs.wankuma.com/nakamura/archive/2008/11/12/161026.aspx"&gt;前に作成したもの&lt;/a&gt;をそのまま流用。
&lt;/p&gt;

&lt;h4&gt;カスタム HandlerAttribute を作成&lt;/h4&gt;
&lt;pre name="code" class="c#"&gt;
public class EventLogCallHandlerAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler()
    {
        return new EventLogCallHandler();
    }
}
&lt;/pre&gt;
&lt;p&gt;
EventLogCallHandler クラスのインスタンスを生成して返しているだけ。
&lt;/p&gt;

&lt;h4&gt;インターセプト対象のメソッドを持つクラスを作成&lt;/h4&gt;
&lt;pre name="code" class="c#"&gt;
public class Wankuma : MarshalByRefObject
{
    // 作成した属性を付与
    [EventLogCallHandler]
    public void Cry()
    {
        Console.WriteLine("クマ～");
    }
}
&lt;/pre&gt;
&lt;p&gt;
作成した EventLogCallHandlerAttribute をCry メソッドに付与しています。
構成ファイルでメソッドを指定する必要はありません。
&lt;/p&gt;
&lt;p&gt;
これで PolicyInjection.Create メソッドで生成した Wankuma インスタンスの、
Cry メソッドが呼び出される前と後にイベントログが出力されます。
&lt;/p&gt;


&lt;h4&gt;まとめ&lt;/h4&gt;
&lt;p&gt;
インターセプトするメソッドの指定は、構成ファイルを記述するよりも、
属性を使った方が遥かに楽ですね。
ちなみに、PIAB には既にロギングや検証など数種類の CallHandler と HandlerAttribute が用意されています。
今回のサンプルで取り上げたロギングは、自作せずに用意されているクラスを使うのも良いでしょう。
&lt;/p&gt;
&lt;img src ="http://blogs.wankuma.com/nakamura/aggbug/161633.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>なかむら</dc:creator><title>Policy Injection Application Block を使ってロギング処理を分離する</title><link>http://blogs.wankuma.com/nakamura/archive/2008/11/12/161026.aspx</link><pubDate>Wed, 12 Nov 2008 00:42:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakamura/archive/2008/11/12/161026.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakamura/comments/161026.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakamura/archive/2008/11/12/161026.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakamura/comments/commentRss/161026.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakamura/services/trackbacks/161026.aspx</trackback:ping><description>&lt;h4&gt;いきなりですが&lt;/h4&gt; &lt;p&gt;簡単なサンプルを。&lt;/p&gt; &lt;p&gt; &lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:66a07148-73bb-4130-b586-d581258727e6" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;class Program
{
    static void Main(string[] args)
    {
        var animal = new Wankuma();

        animal.Cry();

        Console.ReadLine();
    }
}

public class Wankuma
{
    public void Cry()
    {
        Console.WriteLine("クマ～");
    }
}&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;これを実行すると&lt;/p&gt;
&lt;p&gt;&lt;img src="http://nakamura.wankuma.com/blog/images/2008/11/PIABConsole.png"&gt; &lt;/p&gt;
&lt;p&gt;と表示されます。&lt;/p&gt;
&lt;h4&gt;呼び出されたメソッドをログに残したい！&lt;/h4&gt;
&lt;p&gt;私が携わったプロジェクトでは、業務アプリではログを出力する場面がほとんどでした。でもログを出力するコードで汚されるのは嫌…。 &lt;/p&gt;
&lt;h4&gt;そこで Policy Injection Application Block の出番&lt;/h4&gt;
&lt;p&gt;Policy Injection Application Block (以下 PIAB)はアスペクト指向によるソフトウェア開発を可能にするアプリケーションブロックです。PIAB を使う事で、ビジネスロジックなどの本来的な機能から、ロギングや例外処理などの横断的な機能を分離し、外部から注入することができるようになります。 &lt;/p&gt;
&lt;p&gt;さっそく試してみます！ &lt;/p&gt;
&lt;h4&gt;参照するアセンブリを追加 &lt;/h4&gt;
&lt;p&gt;次の2つを追加します。 &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Microsoft.Practices.EnterpriseLibrary.Common&lt;/li&gt;
&lt;li&gt;Microsoft.Practices.EnterpriseLibrary.PolicyInjection&lt;/li&gt;&lt;/ul&gt;
&lt;h4&gt;CustomCallHandler を作成&lt;/h4&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:e3a835e8-2792-4b2d-9db9-1087c51f0b00" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;[ConfigurationElementType(typeof(CustomCallHandlerData))]
public class EventLogCallHandler : ICallHandler
{
    public int Order { get; set; }

    public EventLogCallHandler(NameValueCollection attributes)
    {
        // このコンストラクタは必須みたい
    }

    private const string SOURCE = "PIABSample";

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        // メソッド呼び出し前にログを出力
        EventLog.WriteEntry(SOURCE,
            string.Format("{0} メソッドを呼び出します。", input.MethodBase.Name),
            EventLogEntryType.Information);

        // メソッド呼び出し
        IMethodReturn result = getNext()(input, getNext);

        // メソッド呼び出し後にログを出力
        if (result.Exception != null)
        {
            // 例外が発生したとき
            EventLog.WriteEntry(SOURCE,
            string.Format("{0} メソッド呼び出しで例外が発生しました。", input.MethodBase.Name),
            EventLogEntryType.Error);
        }
        else
        {
            EventLog.WriteEntry(SOURCE,
            string.Format("{0} メソッドを呼び出しました。", input.MethodBase.Name),
            EventLogEntryType.Information);
        }

        return result;
    }
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;イベントログにメソッド名を出力します。
&lt;h4&gt;冒頭のサンプルを書き変えます&lt;/h4&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:7fdb9dd1-3441-4311-a779-218037536658" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;class Program
{
    static void Main(string[] args)
    {
        // PolicyInjection クラスを使って生成
        var animal = PolicyInjection.Create&amp;lt;Wankuma&amp;gt;();

        animal.Cry();

        Console.ReadLine();
    }
}

// MarshalByRefObject から派生させる
public class Wankuma : MarshalByRefObject
{
    public void Cry()
    {
        Console.WriteLine("クマ～");
    }
}&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;最後に構成ファイルを記述&lt;/h4&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:4a32162a-3120-430f-96d8-f4847ba61a28" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;configSections&amp;gt;
        &amp;lt;section name="policyInjection" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration.PolicyInjectionSettings, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
        &amp;lt;section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
    &amp;lt;/configSections&amp;gt;
    &amp;lt;policyInjection&amp;gt;
        &amp;lt;policies&amp;gt;
            &amp;lt;add name="Policy"&amp;gt;
                &amp;lt;matchingRules&amp;gt;

                    &amp;lt;!--Cry メソッドをインターセプトする--&amp;gt;
                    &amp;lt;add match="Cry" ignoreCase="false" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.MethodSignatureMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                      name="Method Signature Matching Rule" /&amp;gt;

                &amp;lt;/matchingRules&amp;gt;
                &amp;lt;handlers&amp;gt;

                    &amp;lt;!--自作の Callhandler を指定--&amp;gt;
                    &amp;lt;add order="0" type="PIABSample.EventLogCallHandler, PIABSample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                      name="Custom Handler" /&amp;gt;

                &amp;lt;/handlers&amp;gt;
            &amp;lt;/add&amp;gt;
        &amp;lt;/policies&amp;gt;
    &amp;lt;/policyInjection&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Cry メソッドをインターセプトして、前後でログを出力します。&lt;/p&gt;
&lt;h4&gt;実行結果&lt;/h4&gt;
&lt;p&gt;&lt;img src="http://nakamura.wankuma.com/blog/images/2008/11/PIABLog.png"&gt; &lt;/p&gt;
&lt;p&gt;メソッド呼び出し前と後の、２つのログが出力されています。 &lt;/p&gt;
&lt;h4&gt;まとめ &lt;/h4&gt;
&lt;p&gt;見ての通り、横断的な機能（ここではロギング）が本来的な機能（鳴き声出力）から分離されているため、スッキリしたコードになりました。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nakamura/aggbug/161026.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>なかむら</dc:creator><title>UnityContainer を拡張する</title><link>http://blogs.wankuma.com/nakamura/archive/2008/11/04/160443.aspx</link><pubDate>Tue, 04 Nov 2008 11:40:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakamura/archive/2008/11/04/160443.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakamura/comments/160443.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakamura/archive/2008/11/04/160443.aspx#Feedback</comments><slash:comments>26</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakamura/comments/commentRss/160443.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakamura/services/trackbacks/160443.aspx</trackback:ping><description>&lt;h4&gt;
はじめに
&lt;/h4&gt;
&lt;p&gt;
UnityContainer を拡張するために UnityContainerExtension クラスが用意されています。
このクラスを継承して独自の Extension を作れば、UnityContainer の挙動を拡張できます。
&lt;/p&gt;
&lt;p&gt;
例として、&lt;a href="http://blogs.wankuma.com/nakamura/archive/2008/10/29/160096.aspx"&gt;先日&lt;/a&gt;のサンプルを書き換えてみます。
&lt;/p&gt;


&lt;h4&gt;
独自の Extension を作成
&lt;/h4&gt;
&lt;pre name="code" class="c#"&gt;
public class AnimalExtension : UnityContainerExtension
{
    protected override void Initialize()
    {
        // 動物クラスを複数まとめて登録する
        Container.RegisterType&amp;lt;IAnimal, Dog&amp;gt;("Dog");
        Container.RegisterType&amp;lt;IAnimal, Cat&amp;gt;("Cat");
        Container.RegisterType&amp;lt;IAnimal, Wankuma&amp;gt;("Wankuma");
    }
}
&lt;/pre&gt;
&lt;p&gt;
Container だけでなく、Policies や Strategies にもアクセスできます。
Policies や Strategies は後日調べる予定。
&lt;/p&gt;


&lt;h4&gt;
作成した Extension を UnityContainer に登録する
&lt;/h4&gt;
&lt;pre name="code" class="c#"&gt;
static void Main(string[] args)
{
    // DI コンテナ生成
    IUnityContainer container = new UnityContainer();

    // Extension を登録
    container.AddNewExtension&amp;lt;AnimalExtension&amp;gt;();

    // 依存性注入済みのインスタンスを生成
    Person person = container.Resolve&amp;lt;Person&amp;gt;();

    person.CallPet();
}
&lt;/pre&gt;


&lt;h4&gt;
もちろん構成ファイルで Extension を指定可能
&lt;/h4&gt;
&lt;pre name="code" class="xml"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;configSections&amp;gt;
        &amp;lt;section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration,Version=1.1.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35"/&amp;gt;
    &amp;lt;/configSections&amp;gt;
    &amp;lt;unity&amp;gt;
        &amp;lt;containers&amp;gt;
            &amp;lt;container name="Sample"&amp;gt;
                &amp;lt;extensions&amp;gt;
                    &amp;lt;add type="ExtensionSample.AnimalExtension, ExtensionSample"/&amp;gt;
                &amp;lt;/extensions&amp;gt;
            &amp;lt;/container&amp;gt;
        &amp;lt;/containers&amp;gt;
    &amp;lt;/unity&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/pre&gt;


&lt;h4&gt;まとめ&lt;/h4&gt;
&lt;p&gt;
自社フレームワークなんかに UnityContainer を採用するなら、
まとめて型を登録できるように Extension を用意した方が良さそうです。
Enterprise Library の各 Application Block も、
構成ファイルの内容を元に型を登録する Extension を提供していますしね。
&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nakamura/aggbug/160443.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>