Curl Global Community
オブジェクトをコピーしたい - Printable Version

+- Curl Global Community (http://communities.curl.com)
+-- Forum: Discussions (http://communities.curl.com/forumdisplay.php?fid=1)
+--- Forum: General Curl questions (http://communities.curl.com/forumdisplay.php?fid=2)
+--- Thread: オブジェクトをコピーしたい (/showthread.php?tid=1067)



オブジェクトをコピーしたい - umemura - 04-11-2014

あるオブジェクトから、別オブジェクトへ値をコピーしたいです。

すべてのフィールドや、getter、setter の値を抜き出して、
別オブジェクトにコピーするには、どうすればいいですか。

リフレクションする方法がわかれば、できそうな気がするのですが・・・。



RE: オブジェクトをコピーしたい - umemura - 04-11-2014

オブジェクト間のコピーは、ClassType、ClassMemberを利用すればできそうですね。
下記、Curl拡張ライブラリの、HashTableUtil.from-object を参考にさせてもらいました。

■Curl拡張ライブラリ
http://developers.curlap.com/re-reference/44-clib05.html


Code:
{import * from CURL.LANGUAGE.REFLECTION}

||オブジェクト間で同一のフィールド、getter、setter の値をコピーする
{define-proc package {copy-object
                         from-obj:any,
                         to-obj:any,
                         search-superclasses?:bool = true,
                         nested-value-proc:{proc-type {type:Type}:bool} =
                             {proc {type:Type}:bool
                                 {return
                                     (not type.parameterized-class?)
                                     and (not {type.subtype-of? Graphic})
                                     and (not type == DateTime)
                                 }
                             }
                     }:any

    ||コピー元のオブジェクトのClasType から、
    ||メンバーの配列を取得
    def from-type = {type-of from-obj} asa ClassType
    def from-members =
        {from-type.get-members
            search-superclasses? = search-superclasses?,
            filter = ClassMember.get-property-filter
        }


    ||コピー先のオブジェクトのClasType から、
    ||メンバーの配列を取得
    def to-type = {type-of to-obj} asa ClassType
    def to-members =
        {to-type.get-members
            search-superclasses? = search-superclasses?,
            filter = ClassMember.get-property-filter
        }

    {for from-member in from-members do
        {if from-member.public? then
            def name = from-member.name
            def type = from-member.type

            ||同一名、同一型のメンバーを検索
            let target-member:#ClassMember  = null
            {for to-member in to-members do
                {if to-member.public? and
                    to-member.name == name and
                    to-member.type == type
                 then
                    set target-member = to-member
                    {break}
                }
            }
            ||コピー元の値を、コピー先のメンバーにセットする
            {if-non-null target-member then
                def from-value =
                    {type-switch from-member
                     case v:Field do
                        {v.get-value from-obj}
                     case v:Getter do
                        {v.get-value from-obj}
                     else
                        {unreachable}
                    }

                {type-switch from-member
                 case v:Field do
                    {v.set-value to-obj, from-value}
                 case v:Setter do
                    {v.set-value to-obj, from-value}
                 else
                    {unreachable}
                }
            }
        }
    }

    {return to-obj}

}

{define-class public DataObjectA
  field public data:String = ""
}

{define-class public CustomDataObjectB {inherits DataObjectA}
  field public custom-data:String = ""
}

{CommandButton
    label ="A -> B",
    {on Action do
        def a = {DataObjectA}
        set a.data = "AAA"
        let b:CustomDataObjectB = {CustomDataObjectB}
        {popup-message
            {Table
                columns = 3,
                "field", "from", "to",
                "", "A", "B",
                "data", a.data, b.data
            }
        }
        {copy-object a, b}
        {popup-message
            {Table
                columns = 3,
                "field", "from", "to",
                "", "A", "B",
                "data", a.data, b.data
            }
        }

    }
}



{CommandButton
    label ="B -> A",
    {on Action do
        let b:CustomDataObjectB = {CustomDataObjectB}
        set b.data = "AAA"
        let a:DataObjectA = {DataObjectA}
        {popup-message
            {Table
                columns = 3,
                "field", "from", "to",
                "", "B", "A",
                "data", b.data, a.data
            }
        }
        {copy-object b, a }
        {popup-message
            {Table
                columns = 3,
                "field", "from", "to",
                "", "B", "A",
                "data", b.data, a.data
            }
        }

    }
}