2014-11-17 2 views
7

C#에서 'with'키워드 (레코드에서 사용할 수 있음)를 모방하고 싶습니다. 나는 새로운 불변의 클래스를 만들 때immutables에 "with"메서드 만들기

지금, 난 그냥 같은 방법 "과"수동으로 일부 사용자를 추가

내 개인 C#을 개발
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); 
    } 
} 

, 내가 할 수있는 일반적인 방법을 만들려고 이 (완벽한 세계에서 나는 F #을 사용할 것입니다). "최고"내가 그랬어입니다 같은 :

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)... 
     } 
    } 

그것은 작동하지만 내가 (지금은 성능 문제의 상관하지 않습니다에 대한) 문자열 매개 변수를 사용하여 시간 오류를 컴파일 상실 때문에 나는 매우 만족 아니에요.

정말 내가 "투사"람다하여 문자열 매개 변수를 대체 아래 코드처럼 뭔가를 쓸 수 있도록하고 싶습니다

:

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

과 같이 보일 것 내 확장 방법 :

  • 이 가능 투사의 resu에 반사를 사용하는 것입니다
    public static TSource With<TSource, TField>(
         this TSource obj, 
         Expression<Func<TSource, TField>> projection, 
         TField value) 
         where TSource : class 
        { 
         // TODO 
        } 
    

    그래서 여기 내 질문 있습니다 그것에서 필드 이름을 얻으려고?

  • 다른 사람이 이미 C#에서 강력한 "with"방법을 사용 했습니까?
+0

제목을 편집했습니다. "[제목에"태그 "가 포함되어 있어야합니까?] (http://meta.stackexchange.com/questions/19190/)"합의가 "아니오, 그렇지 않아야합니다"로 표시되어야합니다. –

+0

첫 번째 질문은 http://stackoverflow.com/questions/671968/retrieving-property-name-from-lambda-expression을 참조하십시오. 두 번째는 StackOverflow에 대한 주제가 아닙니다. 두려워요. –

+1

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

답변

2

이것은 확실히 수행 할 수 있으며 Entity Framework를 비롯한 여러 장소에서 사용되는 접근 방법입니다. EF에서는 쿼리의 속성을 포함하는 데 사용됩니다.

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

이 집합에 대한 쿼리는 범주의 제품을 가져옵니다. 당신은 당신이 표현은 회원이 표현되어 있는지 확인하기 위해 처리 일부 오류가 필요합니다 확장 방법의 발현을 조사하고 실제로 물론이

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

등의 회원 정보를 추출 할 수 있습니다. 그런 다음 리플렉션을 사용하여 적절한 속성을 설정할 수 있습니다. 이 작업을 수행하려면 설정자가 필요하지만 리플렉션을 통해 전용 설정자에 액세스 할 수 있으므로 유형을 효과적으로 변경하지 못할 수 있습니다. 이것은 완벽한 해결책은 아니지만 충분히 가깝습니다.

나는 그런 방법의 기존 구현을 알지 못합니다. 나는 당신의 가득 차있는 버전을보기 위하여 흥미 롭다.

+0

감사합니다. 구현이 끝났을 때이 게시물을 편집합니다. –

0

F #과 C#이 둘 다 .NET 언어이므로 동일한 IL로 컴파일되므로 F #이 어떻게 작동하는지 고려할 수도 있습니다. this-

  • 은 몇 가지 간단한 F # 코드를 컴파일 참조하고 DotPeek 등의 도구를 cdoe하는 IL을 사용하여 C 번호로 디 컴파일 할 수있는 몇 가지 방법이 있습니다. 두 번째 옵션은 IL의 일부 실무 지식을 필요로하지만
  • 일부 F # 코드를 컴파일 및 IL-검사 도구 등 ILDasm

으로 검토, 또한 미묘한 차이점을보고 더 유용 할 수있다 그 C#을 전혀 컴파일하지 못할 수도 있습니다.

+0

"with"는 F # 컴파일러가 인식하는 언어 키워드입니다. 나는 내가 볼 수있는 일리노이 코드가 단지 "생성자 호출"이라고 확신한다. –

관련 문제