2011-10-11 1 views
11

私のオブジェクトでいくつかの文字列のプロパティをトリムする必要がありますが、私はすべてのオブジェクトとプロパティに移動したくない設定されたプロパティでトリムメソッドを行う(300+多くの文字列プロパティ)。すべての文字列のプロパティをトリム

1つのヒント:すべてのオブジェクトにはCoreTransactionというスーパークラスがありますので、私はこれを(少しの反射を使って)より簡単に使用できます。

これは可能ですか?

ありがとうございます。私はあなたのアクセサの振る舞いを変更することについてはよく分からない

// o is your instance object 
List<PropertyInfo> fields = o.GetType().GetProperties() 
     .Where(i => i.PropertyType == typeof(string)); 
fields.ForEach(i => i.SetValue(o, ((string)i.GetValue(o, null)).Trim(), new object[]{})); 
+0

実行時に特定のプロパティ設定ツールで実行するか、すべてのファイルのソースコードを変更しますか? – Oliver

答えて

26
var stringProperties = obj.GetType().GetProperties() 
          .Where(p => p.PropertyType == typeof (string)); 

foreach (var stringProperty in stringProperties) 
{ 
    string currentValue = (string) stringProperty.GetValue(obj, null); 
    stringProperty.SetValue(obj, currentValue.Trim(), null) ; 
} 
+0

あなたの助けていただきありがとうございますが、私はmyObject.propertyString = "foo"を実行すると、setプロパティを "変更"したいと思います。プロパティの値はちょうど "foo"になります。 – rpf

+0

@rpf反射を使用してセッターロジックを変更しようとしていますか? –

+0

はい:$それはあまりにも変ですか? – rpf

2

。そう簡単には聞こえません。ベースクラスにトリムを追加するのはどうですか?

class CoreTransaction 
    { 
     public void Trim() 
     { 
      IEnumerable<PropertyInfo> stringProperties = 
       this.GetType().GetProperties() 
       .Where(p => p.PropertyType == typeof(string) && p.CanRead && p.CanWrite); 

      foreach (PropertyInfo property in stringProperties) 
      { 
       string value = (string)property.GetValue(this, null); 
       value = value.Trim(); 
       property.SetValue(this, value, null); 
      } 
     } 
    } 

(。また、自分のフィールドは読み取りおよび書き込みが可能チェックに注意してください)

 

EDIT:あなたは、あなたのベースクラスに次のようなものを追加することができ、一度にすべてを整えてください。 弱い参照クラスを使用すると、簡単にガベージコレクタの邪魔にならずに自分のインスタンスを追跡できるようになります:

class CoreTransaction 
{ 
    private static List<WeakReference> allCoreTransactions = new List<WeakReference>(); 

    public CoreTransaction() 
    { 
     allCoreTransactions.Add(new WeakReference(this)); 
    } 

    public static void TrimAll() 
    { 
     foreach (WeakReference reference in allCoreTransactions) 
     { 
      if (reference.IsAlive) 
      { 
       ((CoreTransaction)reference.Target).Trim(); 
      } 
     } 
    } 
} 
4

:あなたはこのような何かをするためにリフレクションを使用することができ

11

はOPの問題へのソリューションのためのバラRに感謝します。あなたのソリューションを拡張メソッドに変換し、null値がエラーを投げていた問題を修正しました。 VB.NETを使う人のために

/// <summary>Trim all String properties of the given object</summary> 
    public static TSelf TrimStringProperties<TSelf>(this TSelf input) 
    { 
     var stringProperties = input.GetType().GetProperties() 
      .Where(p => p.PropertyType == typeof(string)); 

     foreach (var stringProperty in stringProperties) 
     { 
      string currentValue = (string)stringProperty.GetValue(input, null); 
      if (currentValue != null) 
       stringProperty.SetValue(input, currentValue.Trim(), null); 
     } 
     return input; 
    } 
+0

ありがとうございます。また、サブクラスのための2番目のforeachループと、IgnoreTrimというプロパティに追加できる属性を追加しました。 – Rhyous

0

、私はthrawnisの答えを変換し、唯一の読み取り専用ではありませんこれらのプロパティを返すに条件を追加しました。そうでない場合、クラスに読み取り専用のプロパティがある場合、それらのプロパティに対してSetValueを実行しようとするとランタイムエラーが発生します。

''' <summary> 
''' Trim all NOT ReadOnly String properties of the given object 
''' </summary> 
<Extension()> 
Public Function TrimStringProperties(Of T)(ByVal input As T) As T 
    Dim stringProperties = input.GetType().GetProperties().Where(Function(p) p.PropertyType = GetType(String) AndAlso p.CanWrite) 

    For Each stringProperty In stringProperties 
     Dim currentValue As String = Convert.ToString(stringProperty.GetValue(input, Nothing)) 
     If currentValue IsNot Nothing Then 
      stringProperty.SetValue(input, currentValue.Trim(), Nothing) 
     End If 
    Next 
    Return input 
End Function 
0

あなたはそれを試すことができますように(私も参照されるクラスにサブクラスと文字列の世話をする拡張メソッドを書かれている

var myinstance = new MyClass(); 
Trim<MyClass>.TrimAllStringFields(myinstance); 
+0

おそらく 'static private action CreatTrimAllStringFields()'の 'typedo'が' Create'に 'e'を見つけられませんでしたか? –

+0

また、修飾子の順序が正しくありません。それは公的/私的な静的なものであり、逆のものではありません。 – Viezevingertjes

4

static public class Trim<T> 
    where T : class 
{ 
    static public readonly Action<T> TrimAllStringFields = Trim<T>.CreateTrimAllStringFields(); 

    static private Action<T> CreatTrimAllStringFields() 
    { 
     var instance = Expression.Parameter(typeof(T)); 
     return Expression.Lambda<Action<T>>(Expression.Block(instance.Type.GetFields(BindingsFlags.Instance| BindingFlags.NonPublic | BindingFlags.Public).Select(field => Expression.Assign(Expression.Field(instance, field)) as Expression), instance).Compile(); 
    } 
} 

はこのようにそれを使用しますparent.Child.Name)

public static class ExtensionMethods 
{ 
    public static void TrimAllStrings<TSelf>(this TSelf obj) 
    { 
     BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; 

     foreach (PropertyInfo p in obj.GetType().GetProperties(flags)) 
     { 
      Type currentNodeType = p.PropertyType; 
      if (currentNodeType == typeof (String)) 
      { 
       string currentValue = (string)p.GetValue(obj, null); 
       if (currentValue != null) 
       { 
        p.SetValue(obj, currentValue.Trim(), null); 
       } 
      } 
      // see http://stackoverflow.com/questions/4444908/detecting-native-objects-with-reflection 
      else if (currentNodeType != typeof (object) && Type.GetTypeCode(currentNodeType) == TypeCode.Object) 
      { 
       p.GetValue(obj, null).TrimAllStrings(); 
      } 
     } 
    } 
} 
1

彼の解決のためにlandiに感謝します。私は、インデックスパラメータを持つクラスのサポートを追加し、また続行する前にobjがnullかどうかをチェックするために、メソッドを変更しました。

public static void TrimAllStrings<TSelf>(this TSelf obj) 
    { 
     if (obj == null) 
      return; 

     BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; 

     foreach (PropertyInfo p in obj.GetType().GetProperties(flags)) 
     { 
      Type currentNodeType = p.PropertyType; 
      if (currentNodeType == typeof(String)) 
      { 
       string currentValue = (string)p.GetValue(obj, null); 
       if (currentValue != null) 
       { 
        p.SetValue(obj, currentValue.Trim(), null); 
       } 
      } 
      // see http://stackoverflow.com/questions/4444908/detecting-native-objects-with-reflection 
      else if (currentNodeType != typeof(object) && Type.GetTypeCode(currentNodeType) == TypeCode.Object) 
      { 
       if (p.GetIndexParameters().Length == 0) 
       { 
        p.GetValue(obj, null).TrimAllStrings(); 
       }else 
       { 
        p.GetValue(obj, new Object[] { 0 }).TrimAllStrings(); 
       } 
      } 
     } 
    } 
関連する問題