11

それぞれが約60本の文字列を持つ複数の大きなオブジェクトがあります。これらの文字列をすべてトリミングする必要があります。this.mystring=this.mystring.Trim()に移動せずにトリミングしたいと思います。代わりに、各オブジェクトが独自の文字列を自動的に検出して操作を実行する方法を探しています。

リフレクションについては少し知っていますが、十分ではありませんが、これは可能だと思いますか?

また、これが重要かどうかはわかりませんが、一部の文字列プロパティは読み取り専用(ゲッターのみ)であるため、これらのプロパティはスキップする必要があります。

ヘルプ?

4

4 に答える 4

15

さて、すべてのプロパティを取得し、どのプロパティが文字列で書き込み可能であるかを見つけるのは簡単です。LINQを使用するとさらに簡単になります。

var props = instance.GetType()
                    .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                    // Ignore non-string properties
                    .Where(prop => prop.PropertyType == typeof(string))
                    // Ignore indexers
                    .Where(prop => prop.GetIndexParameters().Length == 0)
                    // Must be both readable and writable
                    .Where(prop => prop.CanWrite && prop.CanRead);

foreach (PropertyInfo prop in props)
{
    string value = (string) prop.GetValue(instance, null);
    if (value != null)
    {
        value = value.Trim();
        prop.SetValue(instance, value, null);
    }
}

複雑なプロパティの冗長な計算を避けるために、トリミングが実際に違いを生む場合にのみプロパティを設定することをお勧めします。そうでない場合は、問題にならない可能性があります。

必要に応じてパフォーマンスを向上させるさまざまな方法があります。たとえば、次のようなものです。

  • タイプごとに関連するプロパティをキャッシュするだけです
  • Delegate.CreateDelegateゲッターとセッターのデリゲートを構築するために使用する
  • 式ツリーを使用している可能性がありますが、ここで役立つかどうかはわかりません。

ただし、パフォーマンスが実際に問題にならない限り、これらの手順は実行しません。

于 2010-07-11T07:53:42.007 に答える
3

何かのようなもの:

    foreach (PropertyInfo prop in obj.GetType().GetProperties(
        BindingFlags.Instance | BindingFlags.Public))
    {
        if (prop.CanRead && prop.CanWrite && prop.PropertyType == typeof(string)
            && (prop.GetIndexParameters().Length == 0)) // watch for indexers!
        {
            var s = (string)prop.GetValue(obj, null);
            if (!string.IsNullOrEmpty(s)) s = s.Trim();
            prop.SetValue(obj, s, null);
        }
    }
于 2010-07-11T07:54:53.130 に答える
1

IEnumerableprops-loopをチェックインする必要はなく、実際のインスタンスがである場合IEnumerable、propsは無視されます。パーツの修正IEnumerable

private void TrimWhitespace(object instance)
{
    if (instance != null)
    {
        if (instance is IEnumerable)
        {
            foreach (var item in (IEnumerable)instance)
            {
                TrimWhitespace(item);
            }
        }

        var props = instance.GetType()
                .GetProperties(BindingFlags.Instance | BindingFlags.Public)
            // Ignore indexers
                .Where(prop => prop.GetIndexParameters().Length == 0)
            // Must be both readable and writable
                .Where(prop => prop.CanWrite && prop.CanRead);

        foreach (PropertyInfo prop in props)
        {
            if (prop.GetValue(instance, null) is string)
            {
                string value = (string)prop.GetValue(instance, null);
                if (value != null)
                {
                    value = value.Trim();
                    prop.SetValue(instance, value, null);
                }
            }
            else 
                TrimWhitespace(prop.GetValue(instance, null));
        }
    }
}
于 2013-01-07T10:50:18.567 に答える
0

したがって、これを少し拡張するために、リストのリストを含む複雑なオブジェクトがあり、それをトラバースして、すべての子文字列オブジェクトもトリミングしたいと思いました。@Jonから構築したものを彼の回答に投稿しています。それを行うためのより良い方法があったのか、それとも明らかな何かを見逃したのか、私は興味があります。

私が持っているオブジェクトはこれよりも複雑ですが、それは私が何をしようとしていたかを示しているはずです。

public class Customer
{
  public string Name { get; set; }
  public List<Contact> Contacts { get; set; }
}

public class Contact
{
  public string Name { get; set; }
  public List<Email> EmailAddresses {get; set;}
}

public class Email
{
  public string EmailAddress {get; set;}
}


    private void TrimWhitespace(object instance)
    {
        if (instance != null)
        {
            var props = instance.GetType()
                    .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                // Ignore indexers
                    .Where(prop => prop.GetIndexParameters().Length == 0)
                // Must be both readable and writable
                    .Where(prop => prop.CanWrite && prop.CanRead);

            foreach (PropertyInfo prop in props)
            {
                if (instance is IEnumerable)
                {
                    foreach (var item in (IEnumerable)instance)
                    {
                        TrimWhitespace(item);
                    }
                }
                else if (prop.GetValue(instance, null) is string)
                {
                    string value = (string)prop.GetValue(instance, null);
                    if (value != null)
                    {
                        value = value.Trim();
                        prop.SetValue(instance, value, null);
                    }
                }
                else 
                    TrimWhitespace(prop.GetValue(instance, null));
            }
        }
    }

考え?

于 2011-11-02T22:14:15.650 に答える