2009-04-17 5 views
2

저는 LINQ 표현식으로 정적 리플렉션을 공부했습니다. 매우 멋지다!정적 반사에서 온 - 플라이 (On-the-Fly) 필드?

한 가지 생각은 - 한 클래스가 다른 클래스에서 정적 반사를 기반으로 한 클래스의 필드를 '생성'할 수 있습니까? 저는 여기서 여러 번 본 빌더 패턴을 특별히 생각하고 있습니다. 나는 빌드하고자하는 클래스와 일치하는 빌더에 필드를 생성하는 유창한 nhibernate 스타일의 속성 등록을하고 싶습니다. 이 같은 Soemthing이 같은

public class Color 
{ 
    private Color() 
    { 
    } 
    public string Name { get; private set; } 

    public class Builder : BuilderBase<Color> 
    { 
     public Builder() 
     { 
      Property(x => x.Name); 
     } 
     public Build() 
     { 
      return built_up_color; 
     } 
    } 
} 

및 지원 생성자 구문 :

Color c = new Color.Builder() { Name = "Red" }.Build(); 

이 모든 것의 요점은 색상의 properies를 정의하는 반복해야하는 횟수를 줄이는 것입니다. 나는이 함께 연주 : 확실히 작동하고 속성을 여러 번 같은 #을 나열하지만 wordier 덜 유연한 느낌

public class Color 
{ 
    private Color() 
    { 
    } 
    public string Name { get; private set; } 

    public class Builder 
    { 
     private Color _color = new Color(); 
     public string Name 
     { 
      get { return _color.Name; } 
      set { _color.Name = value; } 
     } 

     public Build() 
     { 
      return _color; 
     } 
    } 
} 

합니다. 뭔가 익명 -y를 할 수 있어야하는 것처럼 보입니다.

답변

1

주목할만한 가치 System.Drawing.Color를 사용하여 Color라는 클래스를 충돌시키는 것은 나쁜 생각 일 수 있습니다.

때문이다 매우 다른 혼란을 초래할 가능성이

내가 지적하는 것 (클래스가 더 혼란으로 이어질 수 있습니다 참조 의미를 가지고있는 반면 나쁜 여전히 System.Drawring.Color 값 의미를 가지고) 무엇을 당신이 정말로 원하는 것은 Named Optional Arguments입니다. 번거로운 빌더 클래스를 사용하는 것이 더 많은 노력을 기울일 것이고 C# 4.0에 이르면이 클래스로 이동하는 것이 더 힘들어 질 것이라고 제안합니다. 대신 필요한 생성자를 만드십시오 (또는 클래스의 정적 팩토리 메소드와 형식 서명 충돌을 피할 필요가있을 경우)

+0

우수한 점. 제 경우에는 부품과 자동차가 들어올 수있는 색상을 모델링하려고합니다. ' 어쩌면 내가 영국 동료의 리드와 색상을 따라야한다.) – n8wrl

+1

PartColor를 이름으로 사용하는 것이 좋습니다. 불변이고 작 으면 구조체로 만드는 것이 좋습니다. 그러나 불변 인만큼 충분해야합니다. 문제를 피할 수 있습니다. 저는 브리트니지이지만 맞춤법 프로그래밍에서는 귀화 된 Yank입니다. 색상, 동기화, 등등 :) – ShuggyCoUk

0

나는 그것을 불가능하다고 생각한다. 명시 적으로 선언하는 것 외에는 멤버를 생성 할 수 없다. 글 머리 기호를 물고 Color에 대한 생성자를 선언하십시오.

추신 : 정적 반사는 잘못된 이름입니다. 정적 인 유일한 것은 참조하려는 회원의 조회입니다. 가능한 한 좋은 일이지만 멀리는 아닙니다.

+0

감사를 호출합니다. 나는 색깔을위한 생성자를 가졌지 만, 그것은 매개 변수를 다시 한번 의미합니다. 빌더가 '지나치다'라는 말에 문제가있는 것을 보시겠습니까? – n8wrl

+0

나는 현혹 모드가 켜져 있지 않으면 문제가 보이지 않는다. 그러나 * 나는 * 빌더를 가지고있는 지점을 보지 못했다. –

0

리플렉션을 사용하여 값을 설정하는 수는 적어집니다.

트릭은 컬렉션 초기화 도구를 사용하는 것입니다. 타입 안전합니다.

public class Color 
{ 
    private Color() 
    { 
    } 
    public string Name { get; private set; } 
    public int Prop2 { get; private set; } 

    public class Builder : Builder<Color> 
    { 
     public Builder() 
     { 
      // possible 
      _instance.Name = "SomeDefaultValue"; 
     } 
    } 
} 

class Builder<T> : IEnumerable<string> 
{ 
    protected T _instance = Activator.CreateInstance(typeof(T)); 

    public void Add<TProperty>(Expression<Func<T, TProperty>> prop, TProperty value) 
    { 
     StaticReflection.GetPropertyInfo(prop).SetValue(_instance, value, null); 
    } 

    public static implicit operator T(Builder<T> builder) 
    { 
     return builder.Build(); 
    } 

    public T Build() 
    { 
     return _instance; 
    } 

    IEnumerator<string> IEnumerable<string>.GetEnumerator() 
    { 
     // e.g. return iterator over the property names 
     throw new NotImplementedException(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return ((IEnumerable<string>)this).GetEnumerator(); 
    } 
} 

및 구문 귀하의 답변에 대한

var color = new Color.Builder 
{ 
    { x => x.Name, "foo" }, 
    { x => x.Prop2, 5 } 
}.Build(); 

// or 

var color = new Builder<Color> 
{ 
    { x => x.Name, "foo" }, 
    { x => x.Prop2, 5 } 
}.Build(); 

// or 

Color color = new Builder<Color> 
{ 
    { x => x.Name, "foo" }, 
    { x => x.Prop2, 5 } 
}; 
관련 문제