To można zrobić, ale robi to właściwie ma być dość trudne (i to na pewno nie zmieści się w mojej odpowiedzi). Poniższa prosta realizacja zakłada, że obiekt jest tylko do odczytu i zapisu właściwości i parametrów mniej konstruktora:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
To nieznacznie pokonał punkt, ponieważ prawdopodobnie chcesz użyć tego na niezmiennych typów - ale wtedy zawsze masz wywołanie konstruktora ze wszystkimi argumentami i nie jest jasne, jak połączyć parametry konstruktora (podczas tworzenia instancji) z właściwościami, które można odczytać.
Sposób With
tworzy nową instancję, kopiuje wszystkie wartości nieruchomości, a następnie ustawia ten, który chcesz zmienić (za pomocą PropertyInfo
wyciąg z drzewa wyrażenie - bez jakiejkolwiek kontroli)
public static T With<T, P>(this T self, Expression<Func<T, P>> selector, P newValue)
{
var me = (MemberExpression)selector.Body;
var changedProp = (System.Reflection.PropertyInfo)me.Member;
var clone = Activator.CreateInstance<T>();
foreach (var prop in typeof(T).GetProperties())
prop.SetValue(clone, prop.GetValue(self));
changedProp.SetValue(clone, newValue);
return clone;
}
Poniższy demo zachowuje się zgodnie z oczekiwaniami, ale jak powiedziałem, to ma wiele ograniczeń:
var person = new Person() { Name = "Tomas", Age = 1 };
var newPerson = person.With(p => p.Age, 20);
Generalnie myślę, że stosując metodę uniwersalną do refleksji opartej jak With
tutaj może nie być su Dobry pomysł, chyba że masz dużo czasu na jego prawidłowe wdrożenie. Łatwiej byłoby po prostu zaimplementować jedną metodę dla każdego używanego typu, który pobiera opcjonalne parametry i ustawia ich wartości na sklonowaną wartość (utworzoną ręcznie), jeśli wartość nie jest równa null
. Podpis byłoby coś jak:
public Person With(string name=null, int? age=null) { ... }
Może to będzie przydatne: http://v2matveev.blogspot.com/2010/05/copy-and-update-in-c.html – desco
możliwy duplikat [C#: jak zdefiniować metodę rozszerzenia jako "z "in F #?" (http://stackoverflow.com/questions/6832880/c-how-to-define-an-extension-method-as-with-in-f) –