Odbicie będzie oczywiście nie jest to rozwiązanie najbardziej wydajne, ale z pewnymi modyfikacjami i buforowaniem nadal może być używane.
Oto pomocnik odbicie, które pozwalają na tworzenie kolekcji delegatów mutator i buforować go wewnątrz klasy:
public static class ReflectionHelper
{
public static IEnumerable<PropertyInfo> GetPropertiesOfType<THolder, TPropType>()
{
return typeof(THolder).GetPropertiesOfType(typeof(TPropType));
}
public static IEnumerable<PropertyInfo> GetPropertiesOfType(this Type holderType, Type propType)
{
if (holderType == null)
throw new ArgumentNullException("holderType");
if (propType == null)
throw new ArgumentNullException("propType");
return holderType
.GetProperties()
.Where(prop =>
prop.PropertyType == propType);
}
public static IEnumerable<Action<Func<TPropType, TPropType>>> CreateMutators<THolder, TPropType>(THolder holder)
{
if (holder == null)
throw new ArgumentNullException("holder");
return holder.GetType()
.GetPropertiesOfType(typeof(TPropType))
.Select(prop =>
new
{
getDelegate = (Func<TPropType>)Func.CreateDelegate(
typeof(Func<TPropType>),
holder,
prop.GetGetMethod()),
setDelegate = (Action<TPropType>)Action.CreateDelegate(
typeof(Action<TPropType>),
holder,
prop.GetSetMethod())
})
.Select(accessor =>
(Action<Func<TPropType, TPropType>>)((mutate) =>
{
var original = accessor.getDelegate();
var mutated = mutate(original);
accessor.setDelegate(mutated);
}))
.ToArray();
}
}
Kod klasy - ty buforować mutatorów i używać ich wewnątrz metody przycinania:
class SearchCriteria
{
public SearchCriteria()
{
this.Name = "adsfasd ";
this.Email = " adsfasd ";
this.Company = " asdf adsfasd ";
this.stringMutators = ReflectionHelper.CreateMutators<SearchCriteria, String>(this);
}
public string Name { get; set; }
public string Email { get; set; }
public string Company { get; set; }
// ... around 20 fields follow
private IEnumerable<Action<Func<String, String>>> stringMutators;
private String TrimMutate(String value)
{
if (String.IsNullOrEmpty(value))
return value;
return value.Trim();
}
public void Trim()
{
foreach (var mutator in this.stringMutators)
{
mutator(this.TrimMutate);
}
}
public override string ToString()
{
return String.Format("Name = |{0}|, Email = |{1}|, Company = |{2}|",
this.Name,
this.Email,
this.Company);
}
}
Kod Główny:
var criteria = new SearchCriteria();
Console.WriteLine("Before trim:");
Console.WriteLine(criteria);
Console.WriteLine("After trim:");
criteria.Trim();
Console.WriteLine(criteria);
P.S .: Jednak nie jest to rozwiązanie bardzo bezpośrednie lub jasne, więc polecam iść z "inteligentnym" ustawiaczem (pobierającym), jak to opisano w innych odpowiedziach. Lub, być może, możesz wypróbować jakieś Aspect Oriented Programming approach.
Może można przyciąć struny w swoich ustawieniach nieruchomości? –
Prawdopodobnie przeprojektuję całą klasę tak, aby używała HashMap do zapisywania 20 różnych wartości String, ponieważ wydają się one Listą Opcjonalnych atrybutów. Następnie masz jedną metodę PUT, która może wykonać przycinanie. – Falco
@Falco: skąd wiadomo, że wszystkie są ciągami? Może być "DateTime DayOfBirth". Używanie 'List' byłoby zbyt abstrakcyjne, ponieważ nie możesz powiedzieć: daj mi 'SearchCriteria.Email' już. A jeśli użyjesz 'Dictionary ' musisz znać klucz. –