2

新しくシリアル化されたオブジェクトの値をチェックする効率的な方法について、あなたのアイデアを見てみたいと思います。

例オブジェクトにシリアル化したxmlドキュメントがあり、値チェックを実行したいと思います。私が考えることができる最初の最も基本的なアイデアは、ネストされたifステートメントを使用して各プロパティをチェックすることです。これは、ある値が正しいURL形式であることをチェックすることから、日付であるが日付である別のプロパティ値をチェックすることまでです。正しい範囲など

だから私の質問は、人々がオブジェクトのすべての値をどのようにチェックするのかということです。タイプチェックは重要ではありません。これはすでに処理されているため、値自体と関係があります。非常に大きなオブジェクト用である必要があるため、ネストされたifステートメントを実際に使用したくありませんでした。

編集:

特定のオブジェクトのすべてのプロパティで完全な値の検証を実行したいと思います。

nullではなく自分で値を確認したい。持っている場合は、特定のものの値を確認したいと思います。多くのプロパティを持つオブジェクトは、文字列型で、homepageという名前です。

失敗しない場合は、正しいURL形式の文字列を確認できるようにしたいと思います。これは同じオブジェクトのほんの一例であり、日付が特定の範囲内にあるかどうかを確認できます。そうでない場合は、falseまたは何らかの形式の失敗を返します。

私はc#.net4を使用しています。

4

6 に答える 6

2

Fluent Validationを使用してみてください。これは関心の分離であり、オブジェクトから検証を構成します。

于 2012-09-26T09:27:08.180 に答える
1

ValueResolverでAutomapperを使用することをお勧めします。autommaperを使用して非常に洗練された方法でXMLをオブジェクトに逆シリアル化し、取得した値がValueResolverで有効かどうかを確認できます。

Nullまたは無効なキャストをチェックするベースValueResolverと、取得した値が正しいかどうかをチェックする一部のCustomResolverを使用できます。それはあなたが探しているものと正確には一致しないかもしれませんが、それはそれを行うためのエレガントな方法だと思います。

ここでこれをチェックしてください:http://dannydouglass.com/2010/11/06/simplify-using-xml-data-with-automapper-and-linqtoxml

于 2012-09-26T09:04:16.030 に答える
1
public class Validator<T>
{
    List<Func<T,bool>> _verifiers = new List<Func<T, bool>>();

    public void AddPropertyValidator(Func<T, bool> propValidator) 
    {
        _verifiers.Add(propValidator);
    }

    public bool IsValid(T objectToValidate)
    {
         try {
         return _verifiers.All(pv => pv(objectToValidate));
         } catch(Exception) {
            return false;
         }
    }
}

class ExampleObject {
     public string Name {get; set;}
     public int BirthYear { get;set;}
}


public static void Main(string[] args) 
{
    var validator = new Validator<ExampleObject>();
    validator.AddPropertyValidator(o => !string.IsNullOrEmpty(o.Name));
    validator.AddPropertyValidator(o => o.BirthYear > 1900 && o.BirthYear < DateTime.Now.Year );
    validator.AddPropertyValidator(o => o.Name.Length > 3);

    validator.Validate(new ExampleObject());
}
于 2012-09-26T09:05:25.233 に答える
0

あなたの質問の深さを理解できるかどうかはわかりませんが、あなたはこのようなことをするだけではありませんか?

public SomeClass
{
    private const string UrlValidatorRegex = "http://...

    private const DateTime MinValidSomeDate = ...
    private const DateTime MaxValidSomeDate = ...

    public string SomeUrl { get; set; }

    public DateTime SomeDate { get; set; }

    ...

    private ValidationResult ValidateProperties()
    {
        var urlValidator = new RegEx(urlValidatorRegex);
        if (!urlValidator.IsMatch(this.Someurl))
        {
            return new ValidationResult
                {
                    IsValid = false,
                    Message = "SomeUrl format invalid."
                };
        }

        if (this.SomeDate < MinValidSomeDate 
            || this.SomeDate > MinValidSomeDate)
        {
            return new ValidationResult
                {
                    IsValid = false,
                    Message = "SomeDate outside permitted bounds."
                };
        }

        ...
        // Check other fields and properties here, return false on failure.
        ...

        return new ValidationResult
                {
                    IsValid = true,
                };
    }

    ...

    private struct ValidationResult
    {
        public bool IsValid;
        public string Message;
    }
}

正確な検証コードは、クラスをどのように機能させたいかによって異なりますね。なじみのあるタイプのプロパティを考えてみましょう。

public string SomeString { get; set; }

このプロパティの有効な値は何ですか。nullとの両方は、プロパティで飾られているstring.Emptyことに応じて有効な場合と無効な場合があります。Class許可されるべき最大の長さがあるかもしれませんが、これらの詳細は実装によって異なります。


提案された回答が、パフォーマンスや機能を向上させることなく、上記のコードよりも複雑な場合、より効率的になりますか?

あなたの質問は実際に、多くのコードを書かずにオブジェクトの値をチェックするにはどうすればよいですか?

于 2012-09-26T08:56:35.400 に答える
0

私はあなたの質問が次のとおりだと思います:私のオブジェクトが有効であるかどうかを効率的にチェックするにはどうすればよいですか?

もしそうなら、あなたのオブジェクトがテキストソースから逆シリアル化されただけであるかどうかは問題ではありません。エラーが見つかった場合に逆シリアル化をすばやく停止するために逆シリアル化にオブジェクトをチェックすることに関する質問の場合、それは別の問題であり、質問を更新する必要があります。

オブジェクトを効率的に検証することは、C#や管理ツールに関してはあまり議論されていません。その理由は、どのように行っても非常に速いからです。読みやすく、保守しやすい方法でチェックを行う方法について話し合うのが一般的です。

あなたの質問効率についてなので、ここにいくつかのアイデアがあります:

  • チェックするオブジェクトが非常に多く、パフォーマンスが非常に重要である場合は、オブジェクトをデータの配列に変更して、一貫した方法でチェックできるようにすることができます。例:

MyObjectに多くのプロパティがあるMyObject[]MyObjectsを使用する代わりに、各プロパティを分割して、次のような配列に配置します。

int[] MyFirstProperties
float[] MySecondProperties

このように、リストをトラバースして値をチェックするループは可能な限り高速になり、メモリ内でループフォワードするため、CPUキャッシュで多くのキャッシュミスが発生することはありません。リンクリストとして実装されていない通常の配列またはリストを使用するようにしてください。これにより、多くのキャッシュミスが発生する可能性があります。

  • オブジェクトをプロパティの配列に分割したくない場合は、最高速度は重要ではないようですが、ほぼ最高速度です。次に、最善の策は、オブジェクトをシリアル配列に保持して、次のことを行うことです。

bool wasOk = true;
foreach (MyObject obj in MyObjects)
{
    if (obj.MyFirstProperty == someBadValue)
    {
        wasOk = false;
        break;
    }
    if (obj.MySecondProperty == someOtherBadValue)
    {
        wasOk = false;
        break;
    }
}

これにより、すべてのオブジェクトのプロパティに問題がないかどうかがチェックされます。あなたのケースが実際に何であるかはわかりませんが、あなたは要点を理解していると思います。オブジェクトのプロパティをチェックするだけの場合、速度はすでに優れています。

文字列比較を行う場合は、より洗練された文字列比較を使用するのではなく、可能な限りx = yを使用するようにしてください。これは、x = yにはいくつかのクイックオプトアウトがあるためです。たとえば、いずれかがnullの場合、メモリアドレスがnullの場合は戻ります。同じです、私が正しく覚えていれば、文字列は等しく、いくつかの賢いものがあります。これを読んでいるJavaの人は、Javaでこれを行わないでください!!! 時々動作しますが、常に動作するとは限りません。

私があなたの質問に答えなかった場合、あなたはあなたの質問を改善する必要があります。

于 2012-09-26T09:04:12.803 に答える
0

Haskellなどの関数型言語では、Maybe-monadを使用して問題を解決できます。

多分モナドは、いずれかのステップが出力としてNothingを生成する場合、チェーンを早期に終了することによって、それぞれがNothingを返す可能性のある計算のチェーンを組み合わせる戦略を具体化します。計算に相互に依存する一連のステップが含まれ、一部のステップが値を返さない場合に役立ちます。

Nothingnullに置き換えると、同じことがC#にも当てはまります。

問題を解決する方法はいくつかありますが、どれも特にきれいではありません。何かがnullでないという実行時検証が必要な場合は、AOPフレームワークを使用して、 nullチェックコードを型に挿入できます。そうしないと、nullをチェックする場合にネストを実行する必要があります。これは醜いだけでなく、デメテルの法則に違反する可能性があります。

妥協案として、多分モナドのような拡張メソッドのセットを使用できます。これにより、オブジェクトをクエリし、プロパティの1つがnullの場合の対処方法を選択できます。

Dmitri Nesterukによるこの記事をご覧ください:http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad

お役に立てば幸いです。

于 2012-09-26T09:06:06.573 に答える