0

現在のアプリケーションには次の問題があります。(クラスの例は、Entity Framework Entity クラスとして理解する必要があります。)

さまざまなプロパティの Get/Set の例として、アプリケーション全体で使用されるいくつかのプロパティを保持する静的クラスがあると仮定します。

プロパティの Get は、このプロパティを要求するたびに呼び出されます。何らかのコントロールへのデータバインディングにより、これはおそらくコントロールの再描画 (レイアウトの更新) が発生するたびに発生します。

今、私は状況が発生する可能性があるという問題に直面しています.2つのウィンドウを異なる「静的」値で開きたいのですが、このシナリオを達成するための最良の方法は何ですか?

以下に、理解しやすくするためのいくつかのコードを示します。

クエリで使用されるプロパティを保持する静的クラス:

public static class Core
{
    public string IdLang { get; set; }
    public string IdCompany { get; set; }
}

プロパティ Name の get/set で Core.IdLang を使用するクラス:

public class Car
{
    private string _name;
    public string Name
    {
        get
        {
            _name = (from x in LanguageTables
                    where x.IdLang == Core.IdLang
                    select x.Text).FirstOrDefault();

            return _name;
        }
        set
        {
            if (value == _name)
                return;

            var languageTable = (from x in LanguageTables
                                where x.IdLang == Core.IdLang
                                select x).FirstOrDefault();

            if (languageTable == null)
            {
                languageTable = new LanguageTable();
                languageTable.IdLang = Core.IdLang;
            }

            languageTable.Text = _name;
        }
    }
}

ここで、2 つの異なるウィンドウに 2 つの DataGrid があり、車のリストを 2 つの異なる言語でバインドしたいとします。

私は次のことを行っています(1つのグリッドとウィンドウの例のみ):

public class Window1 : Window
{
    List<Car> Cars;
    public Window1()
    {
        InitializeComponents();
        Core.IdLang = "DE";

        Cars = new List<Car>();            

        //fetch data from Database, and populate the List<Car>

        Grid1.ItemsSource = from x in Cars
                            select x;
    }
}

上記のコード (Window1) をコピーして貼り付けて、2 つ目のウィンドウを作成し、すべての車を英語の名前で表示したいので、次のコードを変更しました。

Core.IdLang = "DE";

Core.IdLang = "EN";

そして、すべてがうまくいくと思っていましたが、後で Core.IdLang を呼び出すどのウィンドウもこの値になり、いずれかのウィンドウで Get/Set が呼び出されると、この言語でのみ受信または変更され、ウィンドウ間で違いはありません。

実際のアプリケーションでは、Core クラスは約 6 つ (またはそれ以上) のプロパティで構成され、50 以上のクラスで使用されます。Car.Name サンプルで確認できるように、すべてのクラスに同じ get/set コードを持つプロパティが少なくとも 1 つあります。

これらのクラスはいずれも、比較のために英語とドイツ語のデータを並べて表示するシナリオで使用できます。

4

2 に答える 2

0

さまざまな値を持ちたいというあなたに基づいて、「そもそもなぜ静的クラスを強制するのですか?」と尋ねます。ほとんどの場合、Entity Framework を扱うときは、T4 ジェネレーターを使用して POCO (Plain Old Class Objects) を作成し、それらに関連付けることができます。ただし、さまざまな言語のプロパティを明示的に保持するセカンダリ レベルを作成したい場合は、'Car' オブジェクトを一番上に定義されたままにしておき、Core Linq ステートメントを削除するのはなぜですか?

ユーザーが間違った値を入力した場合を除いて、この例から何を達成しているのかわかりません。データベースの外部キーの制約のために必要な場合は、常に検証メソッドを個別に追加できます。しかし、最初にコンボボックスなどでユーザーが選択できるセットを制限してみませんか? 次に、さまざまな状況で再利用したり、コンストラクターに入れたりするために保持できる設計図を作成します。以下の例は非常に明確ですが、私のロジックを他のイベント メソッドに入れることもできます。プロパティの get と set をかなり基本的なものに保ち、他の部分で検証を行うようにしています。そうすれば、私見はより適切に型付けされ、パスがどうなるかについての混乱が少なくなります。例えば:

8-11-13 を編集してより具体的にする

// I am the generated POCO form the Entity Model
public class Car
{
    public string IdLang { get; set; }
    public string IdCompany { get; set; }
}

// I am a class for just 'get' methods or update methods potentially
public class GetData
{
     // I am returning a single Entity of 'Car' type based on predicate
     public Car returnSpecificCar(string aLanguage)
    {
        using (EntityName e = new EntityName())
        {
            // I like lambda methods better due to less lines
            return e.Car.FirstOrDefault(n => n.Language == aLanguage);

            // Similar method in Linq style
            // return (from c in e.Car where c.Language == aLanguage
            // select c).FirstOrDefault();
        }
    }

    // I return all cars
    public List<Car> returnAllCars()
    {
        using (EntityName e = new EntityName())
        {
            return e.Car.ToList();
        }
    }
}

// Simple console example
class Program
{
    static void Main(string[] arts)
    {
        GetData d = new GetData();

        var cars = d.returnEntites();
        var specCar1 = d.returnSpecificCar("EN");
        var specCar2 = d.returnSpecificCar("DE");

        string ln = "-----All cars----" + Environment.NewLine;

        cars.ForEach(c => ln += c.CarId + "\t" + c.CarName + Environment.NewLine);

        ln += Environment.NewLine + Environment.NewLine + "----Specific Car1 -----" + Environment.NewLine;

        ln += specCar1.CarID + "\t" + specCar1.CarName+ Environment.NewLine;

        ln += Environment.NewLine + Environment.NewLine + "----Specific Car2 -----" + Environment.NewLine;

        ln += specCar2.CarID + "\t" + specCar2.CarName + Environment.NewLine;

        Console.WriteLine(ln);

        Console.ReadLine();

    }
}

この例で重要なのは、すべての車または特定の車を指定することを選択したことです。戻り値を List に簡単に変更して、言語が 1 対多の関係にある車のリストを返し、それをフィルタリングするだけです。非静的クラスを使用して、一度に 1 つのオブジェクトを異なる方法で返すことができることを示したかっただけです。通常、データベースとは異なる特定の条件付きクラスのリポジトリが必要な場合を除き、データベースの外部でアプリケーションのみを追跡する必要がある場合を除き、POCO をさらに作成する必要はありません。MVVM パターンに従う ViewModel のような UI の表示プラットフォーム用に存在する場合。しかし、データベースにあるものを正確にグリッドに入力するだけで、新しいクラス IMHO を作成する必要はありません。

上記の例で、グリッドに適用したい場合は、頭のてっぺんからそうするだけでよいと思います

GetData d = new GetData();

var items = d.returnEntities();

// Assumes your grid itemname is 'grid'
grid.ItemsSource = items;
于 2013-08-09T16:23:59.073 に答える
0

クラスCore内に外部依存関係があるため、これは非常に脆弱なコードです。Carすべてのクラスに自動的に持たせたい場合IdLangは、継承を使用してそれを達成する必要があります。それ以外の場合は、コンストラクターを介してパラメーターとして使用Dependency Injectionして渡すことができます。CoreCar

個人的には、Coreクラスを持っていてもまったく意味がありません。IdLang と Company の 2 つのプロパティをドロップCarして、コンストラクターを介して初期化できます。

于 2013-08-09T15:49:54.263 に答える