我有多個大對象,每個都有大約60個字符串。我必須修剪所有這些字符串,並且我想這樣做,而不必去this.mystring = this.mystring.Trim()。相反,我正在尋找一種方法來自動讓每個對象發現自己的字符串,然後執行操作。遍歷對象自己的字符串和修剪每個
我對反射有一點了解,但還不夠,但我認爲這是可能的?另外,我不確定這是否重要,但一些字符串屬性是隻讀的(只有一個getter),所以這些屬性將不得不被跳過。
幫助?
我有多個大對象,每個都有大約60個字符串。我必須修剪所有這些字符串,並且我想這樣做,而不必去this.mystring = this.mystring.Trim()。相反,我正在尋找一種方法來自動讓每個對象發現自己的字符串,然後執行操作。遍歷對象自己的字符串和修剪每個
我對反射有一點了解,但還不夠,但我認爲這是可能的?另外,我不確定這是否重要,但一些字符串屬性是隻讀的(只有一個getter),所以這些屬性將不得不被跳過。
幫助?
嗯,很容易獲得所有的屬性,並找出哪些是字符串和可寫的。 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
打造爲干將代表和setter我不會採取任何這些步驟,除非性能但e實際上是一個問題。
喜歡的東西:
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);
}
}
無參數類型。GetProperties()'調用包含靜態屬性,我懷疑*不應該包含在這裏。 – 2010-07-11 07:57:11
@Jon - 很好,謝謝。我不會提到'IsReadable'; p另外 - 你可能想檢查索引器。 – 2010-07-11 08:00:41
@Marc:將修復:) – 2010-07-11 08:17:23
所以對這個有點擴大,我有一個列表的列表一個複雜的對象,我想遍歷和修剪所有的子串的對象以及。我正在發佈我在@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));
}
}
}
的思考?
不需要在道具循環中檢查IEnumerable
,並且如果實際實例是IEnumerable
,道具將被忽略。修復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));
}
}
}
我以爲屬性樹會自動緩存,如果不是在調試模式?我讀了幾次。這是不是真的? – Alex 2010-07-11 08:01:45
在這種情況下,即使在4.0中,「表達式」也是一種痛苦;不過,將多個「動作」組合成一個代表會很好。 –
2010-07-11 08:01:54
@Alex - * source *中的lambda表達式可以使用後臺代理字段來做一些聰明的事情。然而,在運行時,AFAIK並不是真正的手動編譯樹('Compile')。 – 2010-07-11 08:03:33