Seasarプロジェクト ＞ Seasar.NETプロジェクト ＞ S2Container.NET ＞ S2Dxo

# 目次

上へ

- S2Dxoとは
- クイックスタート
- Dxoの定義
- 変換ルール
- 変換のカスタマイズ

S2Dxo.NETを使用するときには、 アプリケーション構成ファイルの<assemblys>にアセンブリ(Seasar.Dxo)を指定します。

# S2Dxoとは

上へ

DXO (Data eXchange Object) とは，PONO(Plain Old NET Object)とPONO、PONOとCollection、PONOとDictionaryを相互変換 (exchange)することを目的としたオブジェクトです．主な用途としては，プレゼンテーション層のモデル (ページ) とドメイン層のモデル (エンティティ) を相互変換することを意図しています．

S2DxoはDXOを実現するためのフレームワークです．S2Dxoを使うと，インタフェースを定義するだけで DXOを実現することが可能となります．

# クイックスタート

上へ

さっそく試してみましょう．登場人物はC#の場合、次のようになります．

変換元のPONO
EmployeeとDepartmentの二つ．EmployeeはDepartmentを参照します．

変換先のPONO
EmployeePage．EmployeePageはEmployeeとDepartmentの両方のプロパティを持っています．

変換を行うDXO
EmployeeDxo．EmployeeとDepartmentをEmployeePageに変換するDXOのインタフェースです．

S2Dxoは，上記3つのPONOに対して，以下の図のような変換を行います．

##### Employee.cs

変換元のPONOです．Departmentを参照します．

    namespace Seasar.Tests.Dxo
    {
        public class Employee
        {
            private Department _department;
            private string _ename;

            public string EName
            {
                get { return _ename; }
                set { _ename = value; }
            }

            public Department Department
            {
                get { return _department; }
                set { _department = value; }
            }
        }
    }

##### Department.cs

変換元のPONOです．Employeeから参照されます．

    namespace Seasar.Tests.Dxo
    {
        public class Department
        {
            private string _dname;

            public string DName
            {
                get { return _dname; }
                set { _dname = value; }
            }
        }
    }

##### EmployeePage.cs

変換先のPONOです．EmployeeのプロパティENameに加えて，DepartmentのプロパティDepartmentも 持っています．

    namespace Seasar.Tests.Dxo
    {
        public class EmployeePage
        {
            private string _dname;
            private string _ename;

            public string Department
            {
                get { return _dname; }
                set { _dname = value; }
            }

            public string EName
            {
                get { return _ename; }
                set { _ename = value; }
            }
        }
    }

##### IEmployeeDxo.cs

変換を行うDXOです．引数として変換元のPONOであるEmployeeを受け取り，戻り値として 変換先のPONOであるEmployeePageを返します．単なるインタフェースで実装がないことに 注目してください．

また、逆にEmployeePageからEmployeeへの変換も出来ます

    namespace Seasar.Tests.Dxo
    {
        public interface IEmployeeDxo
        {
            EmployeePage ConvertToEmployeePage(Employee emp);

            void ConvertPageToEmp(EmployeePage page, Employee emp);
        }
    }

##### app.dicon

EmployeeDxoを利用するために必要な設定を記述します．

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
    "http://www.seasar.org/dtd/components21.dtd">
    <components namespace="dxo">
        <!-- インターセプタ -->
        <component name="interceptor" class="Seasar.Dxo.Interceptor.DxoInterceptor"/>

        <!-- コンポーネント -->
        <component class="Seasar.Tests.Dxo.IEmployeeDxo">
            <aspect pointcut="*">interceptor</aspect>
        </component>
    </components>

実行クラスの中では次のように記述します．

    [Test, S2]
    public void TestSimple()
    {
            Include(PATH);
            IEmployeeDxo dxo = (IEmployeeDxo) GetComponent(typeof (IEmployeeDxo));

            Employee employee = new Employee();
            employee.EName = "Mike";
            Department dept = new Department();
            dept.Department = "Sales";
            employee.Department = dept;

            EmployeePage page = dxo.ConvertToEmployeePage(employee);
            Assert.AreEqual("Mike", page.EName, "EName");
            Assert.AreEqual("Sales", page.Department, "Department");
            if (!String.IsNullOrEmpty(page.Name))
                Assert.Fail("Name2");

    }

# Dxoの定義

上へ

### インターフェイス定義

Dxoは通常インターフェイスとして定義します。

次のようになります。

C#

    public interface IFooDxo
    {
    	...
    }

VB

    Public Interface IFooDxo
    	...
    End Interface

### メソッド定義

Dxoには変換を行うメソッドを定義します。メソッド名は自由に定義できますが、 慣例的にConvertで始めます。

DXOのメソッドは次の2つの形式のいずれかにすることができます。

- 変換先型 メソッド名(変換元型)
- void メソッド名(変換元型, 変換元型)

戻り値が変換後型の場合はS2Dxo.NETがインスタンスを生成して返します。 戻り値がvoidの場合は第2引数で受け取ったインスタンスを更新します。

変換前及び変換後の型の組み合わせは次のものがサポートされています。

変換前型 | 変換後型
--- | ---
PONO | PONO
PONO[] | PONO[]
PONO | System.Collections.Generic.IList<PONO>
System.Collections.Generic.IList<PONO> | System.Collections.Generic.IList<PONO>
PONO | System.Collections.IDictionary
System.Collections.IDictionary | PONO

例えば次のようになります。

C#

    public interface IFooDxo
    {
            void ConvertPonoToPono(FromBean fromBean, ToBean toBean);
            ToBean ConvertToPono(FromBean fromBean);

            void ConvertFromArrayToArray(FromBean[] fromArray, ToBean[]toArray);
            ToBean[] ConvertToArray(FromBean[] fromArray);

            void ConvertListToList(IList<FromBean> fromArray, IList<ToBean> toArray);
            List<ToBean> ConvertToList(IList<FromBean> toArray);

            void ConvertToDictinary(FromBean emp, IDictionary dict);
            void ConvertFromDictionaryToPONO(IDictionary dict, FromBean emp);

    }

### インターセプタの適用

DXOインタフェースにはS2Dxo.NETの提供するインターセプタを適用します

    <components namespace="dxo">
        <!-- インターセプタ -->
        <component name="interceptor" class="Seasar.Dxo.Interceptor.DxoInterceptor"/>
    </components>

# 変換ルール

上へ

### 変換の基本

PONOまたはIDictionaryからPONOに変換する場合，変換先となるPONOのプロパティを変換元から探し， (必要なら)型変換を行って変換先のプロパティに設定します．

PONOからIDicitionaryに変換する場合は，変換元のPONOの全プロパティについて変換先の IDictionaryに追加します．追加されるエントリのキーは変換元のプロパティ名(string)，値は変換元のプロパティ値です.

### 型変換

変換元と変換先の型が異なる場合は型変換が行われます.S2Dxoが標準で提供する型変換は以下の通りです.変換先の型を基準に参照してください.

変換元の型 | 変換先の型 | 説明
--- | --- | ---
bool | bool | -
short, int, long | 1以上であればtrue, それ以外はfalseに変換．
その他任意の型 | 変換元を文字列化し、それが"yes", "y", "true", "on", "1"の いずれかならばtrue, そうでなければfalseに変換
bool | short, int, long | 変換元がtrueなら1，そうでなければ0に変換．
short, int, long | 同等の値に変換します．
string | 文字列の表現する数値と同等の値に変換します．
char | char | -
string | string | -
char[] | 変換元を文字シーケンスとして持つstringに変換します．
System.DataTime | DatePattern属性に従い変換します． 詳細は「日付・時刻のフォーマット」を参照してください．
char[] | char[] | -
string | 変換元の持つ文字配列に変換します．
System.DateTime | System.DateTime | -
long | 変換元のlong値を時刻値として持つSystem.DateTimeに変換します．
string | DatePattern属性に従いSystem.DateTimeに変換します． 詳細は「日付・時刻のフォーマット」を参照してください．
PONO | PONO | 変換元PONOを変換先PONOに変換します． 変換元PONOのプロパティは変換先PONOの対応するプロパティに変換されます．

# ネストしたPONOのプロパティ

上へ

変換先のPONOに存在するプロパティと同名のプロパティが変換元のPONOに存在しない場合， S2DxoはネストしたPONOのプロパティを探します．ネストしたPONOのプロパティとは， 変換元PONOが持つPONOを型とするプロパティのプロパティです.

この探索はJava版と同様に一段階のみ行われます．

C#

    public class Employee
    {
        private  Department _department;
        public Department Dept
        {
           get { return _department; }
           set { _department = value; }
        }
    	...
    }

    public class Department
    {
        private  string _dname;
        public string DName
        {
           get { return _dname; }
           set { _dname = value; }
        }
    	...
    }

    public class EmployeePage
    {
        private  string _dname;
        public string DName
        {
           get { return _dname; }
           set { _dname = value; }
        }
    	...
    }

上の例で，EmployeeからEmployeePageへの変換を行うと，EmployeePageのDNameプロパティには， 　　　　　EmployeeのDeptプロパティが参照する，DepartmentのDNameプロパティが設定されます．

# 変換のカスタマイズ

上へ

### 変換元プロパティの指定

変換元PONOまたはマップのプロパティ名と変換先PONOまたはマップのプロパティ名が 異なる場合は属性で変換ルールを指定することができます．

変換元のプロパティと変換先のプロパティをSeasar.Dxo.Annotation.ConversionRuleAttributeで指定します．

例えば次のようになります。

C#

    public interface IFooDxo
    {
        [ConversionRule(PropertyName = "EName", TargetPropertyName = "DName")]
        [ConversionRule("DName","EName")]
        ToBean ConvertBeanToTarget(FromBean source);
    }

VB

    Public Interface IFooDxo
        <ConversionRule(PropertyName = "EName", TargetPropertyName = "DName")> _
        <ConversionRule("DName","EName")> _
        Function ConvertBeanToTarget(ByVal source As FromBean) As ToBean
    End Interface

### 日付時刻のフォーマット

System.DateTimeとstringとの相互変換を行う場合にはフォーマットパターンを指定できます．

フォーマットパターンは解釈することができるパターン文字列で，DXOインタフェースのメソッドにSeasar.Dxo.Annotation.DatePatternAttributeで指定することができます．属性が指定されたメソッドで行われる変換の際に，PONOのプロパティにSystem.DateTimeとstringとの変換が必要になると，指定されたフォーマットパターンが使われます．フォーマットパターンが指定されなかった場合は，デフォルトロケールのデフォルトパターンが使われます．

例えば次のようになります。

C#

    public interface IFooDxo
    {
        [DatePattern("yyyyMMdd")]
        ToBean ConvertBeanToTarget(FromBean source);
    }

VB

    Public Interface IFooDxo
        <DatePattern("yyyyMMdd")> _
        Function ConvertBeanToTarget(ByVal source As FromBean) As ToBean
    End Interface

© Copyright The Seasar Project and the others 2004-2009, all rights reserved.