-1

ネストされたクラスの配列を含むLINQをインスタンスに設定しようとしています。私は次のLINQでこれを行うことができました。インスタンスを構成するクラスもselectに含めました。

    select new EditableWarrantBook {
        Id = p1.id,
        Comment = p1.EntryComment,
        WarrantYear1 = new BookYear {
            StatusYear = p2.StatusYear,
            Status = p2.Status,
        },
        WarrantYear2 = new BookYear {
            StatusYear = p3.StatusYear,
            Status = p3.Status,
        },
        WarrantYear3 = new BookYear {
            StatusYear = p4.StatusYear,
            Status = p4.Status,
        }
    }

public class EditableWarrantBook
{
    public int Id { get; set; }
    public string Comment { get; set; }

    public BookYear[] WarrantYear = new BookYear[3];

    public BookYear WarrantYear1
    {
        get { return WarrantYear[0]; }
        set { WarrantYear[0] = value; }
    }
    public BookYear WarrantYear2
    {
        get { return WarrantYear[1]; }
        set { WarrantYear[1] = value; }
    }
    public BookYear WarrantYear3
    {
        get { return WarrantYear[2]; }
        set { WarrantYear[2] = value; }
    }

}

public class BookYear
{
    public int? StatusYear { get; set; } 
    public string Status { get; set; } 
}

WarrantYear[0]これは機能します。またはのいずれかで値にアクセスできますWarrantYear1。これは、UIを設計するときに役立つ場合があります。ただし、この場合、WarrantYear1これをJSONに変換し、繰り返す必要がないため(または、ネットワーク上で同じデータの2つのバージョンを送信する必要があるため)、プロパティは必要ありません。私の質問は、WarrantYear配列をロードするためのselectステートメントをどのように書くかです。または、プロパティとして配列にアクセスできるようにクラスを作成するにはどうすればよいですか。私のソリューションには、クラスのWarrant1, Warrant2, Warrant3プロパティが含まれていてはなりません。EditableWarrantBook

4

2 に答える 2

1

Warrant1、Warrant2、Warrant3プロパティがないとselectを機能させることができなかったので、そのままにしてクラスを書き直し、JSONシリアライザーがWarrant1、Warrant2、Warrant3プロパティなしでJSONのインスタンスを作成するようにしました。この記事のリフレクションを使用しました。問題を明確にするために、最初の試みは、JSONシリアライザーがWarrant1、Warrant2、Warrant3構造の両方を作成し、Warrant []配列を作成していたため、必要な2倍の大きさのJSONペイロードを作成することでした。Warrant []配列のみを使用してJSON結果の基本クラスでクラスを書き換えると、Webサービスのインターフェイス要件が満たされました。

namespace my.Models
{
public class WarrantBook
{
    public int Id { get; set; } 
    public string Comment { get; set; }

    BookYear[] warrantYear = new BookYear[3];

    public BookYear[] WarrantYear
    {
        get { return warrantYear; }
        set { warrantYear = value; }
    }
}

public class EditableWarrantBook : WarrantBook  
{
    public BookYear WarrantYear1
    {
        get { return WarrantYear[0]; }
        set { WarrantYear[0] = value; }
    }
    public BookYear WarrantYear2
    {
        get { return WarrantYear[1]; }
        set { WarrantYear[1] = value; }
    }
    public BookYear WarrantYear3
    {
        get { return WarrantYear[2]; }
        set { WarrantYear[2] = value; }
    }

}
public class BookYear
{
    public int? StatusYear { get; set; } 
    public string Status { get; set; } 
}

public static class Ext
{
    public static void CopyProperties(this EditableWarrantBook  source, WarrantBook destination)
    {
        // Iterate the Properties of the destination instance and   
        // populate them from their source counterparts   
        PropertyInfo[] destinationProperties = destination.GetType().GetProperties();
        foreach (PropertyInfo destinationPi in destinationProperties)
        {
            PropertyInfo sourcePi = source.GetType().GetProperty(destinationPi.Name);
            destinationPi.SetValue(destination, sourcePi.GetValue(source, null), null);
        }
    }
}

}

使用法WCFRESTWebサービス

        [WebGet(UriTemplate = "GetWarrant?id={s}&user={user}")]
    public WarrantBook GetWarrant(string s, string user)
    {
        int id;
        if (int.TryParse(s, out id))
        {
            EditableWarrantBook model = SessionWarrantBook.One(p => p.Id == id);
            model.CheckedOutBy = user; // need to add checkout code
            WarrantBook jsonModel = new WarrantBook();
            model.CopyProperties(jsonModel);
            return jsonModel;
        }
        return new WarrantBook();
    }
于 2012-05-21T14:05:42.900 に答える
0

問題は、SQLの世界(クエリの構築)とCLRの世界(新しいオブジェクトの作成)を混在させようとしていることです。これを回避する方法は、クエリを最初のデータフェッチクエリ(SQLワールド)に分割し、結果を列挙してオブジェクト(CLRワールド)に変換することです。

したがって、の後にwhere p1.SaleYear == 2009、これを追加します。

select new { p1, p2, p3, p4 })
.AsEnumerable()
.Select(tr => new EditableWarrantBook
    {
    Id = tr.p1.id,
    Comment = tr.p1.EntryComment,
    WarrantYear = new[] {
        tr.p2 == null ? (BookYear)null : new BookYear // EDITED LINE
        {
            StatusYear = tr.p2.StatusYear,
            Status = tr.p2.Status,
        },
        tr.p3 == null ? (BookYear)null : new BookYear // EDITED LINE
        {
            StatusYear = tr.p3.StatusYear,
            Status = tr.p3.Status,
        },
        tr.p4 == null ? (BookYear)null : new BookYear // EDITED LINE
        {
            StatusYear = tr.p4.StatusYear,
            Status = tr.p4.Status,
        }}
    }).ToList();

クエリ構文を維持したい場合は、次のように変更してください。

result = from tr in 
    (/*Select up to the AsEnumerable call above)*/).AsEnumerable()
    select new EditableWarrantBook
        {
            /* Initialization code supplied above */
        }

編集:それで、もう一度例を変更しました。返される値の1つがnullのように見えるので、nullオブジェクトのプロパティにアクセスしていないことを確認するためにnullチェックを追加しました(ただし、nullをチェックしませんでしたp1)。

于 2012-05-18T20:15:34.607 に答える