2014-11-17 9 views
7

Chciałbym naśladować F # "z" słowa kluczowego (które mogą być używane na rekordach) w języku C#.Tworzenie metody "z" na immutables

Teraz, gdy tworzę nową klasę niezmienna, po prostu dodać ręcznie niektóre niestandardowe „z” metodami tak:

public class MyClass 
{ 
    public readonly string Name; 
    public readonly string Description; 

    public MyClass(string name, string description) 
    { 
     this.Name = name; 
     this.Description = description; 
    } 

    // Custom with methods 
    public MyClass WithName(string name) 
    { 
     return new MyClass(name, this.Description); 
    } 

    public MyClass WithDescription(string description) 
    { 
     return new MyClass(this.Name, description); 
    } 
} 

Dla mojego osobistego C# rozwoju, starałem się stworzyć metody rodzajowe zrobić to (w idealnym świecie użyłbym F #). „Najlepsze” Zrobiłem coś takiego jak:

public static class MyExtensions 
    { 
     public static TSource With<TSource, TField>(
      this TSource obj, 
      string fieldName, 
      TField value) 
      where TSource : class 
     { 
      // Reflection stuff to use constructor with the new value 
      // (check parameters names and types)... 
     } 
    } 

To działa, ale nie jestem całkiem zadowolony, bo tracę czas kompilacji błędów za pomocą parametru ciąg (na razie nie dbam o problemy z wydajnością).

Naprawdę chciałbym, aby móc napisać coś jak poniżej kod, gdzie zastąpi ciąg parametru przez „projekcji” lambda:

var myClass1 = new MyClass("name", "desc"); 
var myClass2 = myClass1.With(obj => obj.Name, "newName"); 

Moja metoda rozszerzenie będzie wyglądać następująco:

public static TSource With<TSource, TField>(
     this TSource obj, 
     Expression<Func<TSource, TField>> projection, 
     TField value) 
     where TSource : class 
    { 
     // TODO 
    } 

Więc oto moje pytania:

  • Czy można użyć refleksji na resu projekcji lt i otrzymasz od niego nazwę pola?
  • Czy ktoś już wykonał solidną metodę "z" w języku C#?
+0

Edytowałem twój tytuł. Zobacz, "[Czy w tytułach pytania powinny znaleźć się" znaczniki "?] (Http://meta.stackexchange.com/questions/19190/)", gdzie konsensus brzmi "nie, nie powinien". –

+0

Aby uzyskać pierwsze pytanie, zobacz http://stackoverflow.com/questions/671968/retrieving-property-name-od-lambda-expression. Twoja druga kwestia nie dotyczy tematu StackOverflow Obawiam się. –

+1

Zobacz także http://stackoverflow.com/questions/2820660/get-name-of-property-as-a-string –

Odpowiedz

2

Z pewnością można to zrobić i jest podejście stosowane w wielu miejscach, w tym w Entity Framework. W EF służy do włączenia właściwości w zapytaniu.

DbContext.Categories.Include(c=>c.Products) 

Zapytanie dotyczące tego zestawu spowoduje również pobranie produktów z kategorii. Można badać ekspresję w wybranej metody wydłużania i wyodrębnić Informacje Użytkownik jak ten

((System.Linq.Expressions.MemberExpression)projection.Body).Member 

oczywiście w praktyce trzeba będzie jakiś błąd obsługi aby upewnić się, że wyrażenie jest wyrażeniem członkiem. Następnie możesz użyć odbicia, aby ustawić odpowiednią właściwość. Będziesz potrzebował setera, aby to zadziałało, ale możesz uzyskać dostęp do prywatnych seterów za pomocą refleksji, więc typy wciąż mogą być skutecznie niezmienne. To nie jest idealne rozwiązanie, ale wydaje mi się, że jest wystarczająco blisko.

Nie jestem świadomy żadnej istniejącej implementacji takiej metody. Jestem ciekawa twojej pełnej wersji.

+0

Dzięki, będę edytować ten post po zakończeniu mojej implementacji. –

0

Ponieważ F # i C# są obydwoma językami .NET i tym samym kompilują do tego samego IL, można również rozważyć, w jaki sposób F # wykonuje swoją pracę pod maską. Istnieje kilka sposobów, aby zobaczyć to-

  • Kompilacja jakiś prosty kod F #, a następnie dekompilować go w C# za pomocą IL do cdoe narzędzia takiego jak DotPeek.
  • Kompilacja trochę F # Kod i zbadać go za pomocą narzędzia IL-kontroli, takich jak ILDasm

choć druga opcja wymaga pewnej wiedzy roboczy IL, może również okazać się bardziej przydatna widząc niektóre subtelnych różnic że C# może nie być w stanie skompilować się w ogóle.

+0

"with" jest słowem kluczowym języka, znanym z kompilatora F #. Jestem pewien, że jedyny kod IL, który zobaczę, to "po prostu" wywołanie konstruktora. –

Powiązane problemy