3

ここで何が起こっているのか、そしてそのように動作するべきかどうかを理解するのを手伝ってください。CMS からのオブジェクトの一般的なリストがあります。

たとえばList<MyCMS.Articles.Article> myArticles = articles.All

後で、リストの内容を JSON 形式で出力します (CMS UI 用 - テーブル リスト)。

これで、単一のレコードには次が含まれます。

article.Title
article.Alias
article.Guid
article.Description
+
article.SeoProperties.TitleOverride
article.SeoProperties.H1Tag
article.StateProperties.IsActive
article.StateProperties.Channels

等...

ご覧のとおり、Article オブジェクトには追加のクラス プロパティがあり、共通のプロパティがあります (CMS の他のオブジェクト タイプで使用されます)。

また、コレクションに対して LINQ でいくつかのフィルター操作を行うフィルター クラスを使用して、特定のチャネル内の記事のみを返します。たとえば...

したがって、問題は、コレクションを JSON としてシリアル化すると、テーブル リストに実際に表示する必要がある「列」がわずかしかなく、他のフィールドには必要ないことです。特に、「説明」などの長いフィールドが必要になる可能性があります。 " (ファイル システムからの遅延読み込み) など... - DataContractJsonSerializer でシリアル化します...

JSON結果に含まれるフィールドを制御する方法が必要です...プロパティが必要ない場合はリフレクションを使用してプロパティ値をnullに設定し、クラスプロパティを[DataMember(IsRequired = false]で装飾します、EmitDefaultValue = false)] 属性... - うまくいくはずです - しかし - フィールドを取り除く最終的なオブジェクトのコレクション (クローンさえも!!) に行くとすぐに = 値を「null」に設定します - プロパティ値は次のようになりますnull - アプリケーション全体 - そのようなオブジェクトのすべてのコレクションで...え?

ここにいくつかのデモコードがあります:

void Page_Load() {
        MyCms.Content.Games games = new MyCms.Content.Games();
        List<MyCms.Content.Games.Game> allGames = games.All;

        MyCms.Content.Games games2 = new MyCms.Content.Games();
        List<MyCms.Content.Games.Game> allGamesOther = games2.All;

        Response.Write("Total games: " + allGames.Count + "<br />");

        //This is our fields stripper - with result assigned to a new list
        List<MyCms.Content.Games.Game> completelyUnrelatedOtherIsolated_but_notSureList = RemoveUnusedFields(allGamesOther);

        List<MyCms.Content.Games.Game> gamesFiltered = allGames.Where(g=>g.GamingProperties.Software=="89070ef9-e115-4907-9996-6421e6013993").ToList();

        Response.Write("Filtered games: " + gamesFiltered.Count + "<br /><br />");

    }

    private List<MyCms.Content.Games.Game> RemoveUnusedFields(List<MyCms.Content.Games.Game> games)
    {
        List<MyCms.Content.Games.Game> result = new List<MyCms.Content.Games.Game>();

        if (games != null && games.Count > 0)
        {
            //Retrieve a list of current object properties
            List<string> myContentProperties = MyCms.Utils.GetContentProperties(games[0]);

            MyCms.PropertyReflector pF = new MyCms.PropertyReflector();

            foreach (MyCms.Content.Games.Game contentItem in games)
            {
                MyCms.Content.Games.Game myNewGame = (MyCms.Content.Games.Game)contentItem.Clone();
                myNewGame.Images = "wtf!"; //just to be sure we do set this stuff not only null

                pF.SetValue(myNewGame, "GamingProperties.Software", ""); //set one property to null for testing

                result.Add(myNewGame);

            }
        }

    return result;
}

オブジェクトは、次のように「デフォルト値」(基本的に、ほとんどの場合 null) に設定されます。

 private object GetDefaultValue(Type type)
        {
            if (type.IsValueType)
            {
                try
                {
                    return Activator.CreateInstance(type);
                }
                catch {
                    return null;
                }
            }

            return null;
        }
4

2 に答える 2

2

おそらく、浅いコピーと深いコピーを区別するのに問題があるでしょう。

フィールドが値型の場合、フィールドのビットごとのコピーが実行されます。フィールドが参照型の場合、参照はコピーされますが、参照されるオブジェクトはコピーされません。したがって、元のオブジェクトとそのクローンは同じオブジェクトを参照します

オブジェクトを複製し、そのオブジェクトに参照型のフィールドがある場合、ディープ コピーを使用すると、そのオブジェクトの新しい複製が作成され、フィールドに割り当てられます (最初のオブジェクトを参照するだけではありません)。したがって、何も共有しない完全に異なるオブジェクトが必要です。

つまり、クローンを使用していて、一部のプロパティが実際にはサブプロパティ (つまり、元のオブジェクト内のインスタンスのプロパティ) である場合、新しいオブジェクトではなく参照に基づいて操作しているため、アプリケーション全体で変更していることになります。サブオブジェクトのインスタンス。

あなたはそれについてのより多くの情報を持っています

http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx

于 2011-01-12T13:44:46.937 に答える
0

必要なフィールドを使用して一種のモデルビュークラスを作成し、Automapperなどを使用してそれらを入力することができます。このようにして、優れたコード、保守が容易、高度にカスタマイズ可能なコードが得られます。

于 2011-01-12T13:13:19.800 に答える