2012-11-06 2 views
1

클래스에서 몇 가지 유효성 검사를 수행하려고하므로 특성을 사용할 수 있다고 생각했습니다. 이처럼 :속성 장식 속성의 값 가져 오기

public class someClass 
{ 
    [Lenght(200)] 
    public string someStr { get; set; } 
} 
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] 
sealed class Lenght : Attribute 
{ 
    public Lenght(int Lenght) 
    { 
     //some code 
    } 
} 

그러나 나는이 일을 속성없는 방법이기 때문에 나는 그것을 할 수 있다는 것을 알고. 그리고, 방법이 있다면, 나는 피하고 싶은 무거운 반성과 불투명 함을 사용할 것입니다.

내가하고 싶은 검증은 다음과 같이이다 :

public class someClass 
{ 

    public string someStr 
    { 
     get 
     { 
      return _someStr; 
     } 
     set 
     { 
      if (value.Length > 200) 
      { 
       throw new Exception("Max Length is 200!"); 
      } 
      else _someStr = value; 
     } 
    } 
    private string _someStr { get; set; } 
} 

하지만이 모든 코드없이, 빨리하고 싶어. 나는 속성을 사용하는 것만큼 빨리 원한다.

내가 할 수있는 방법이 있습니까?

답변

1

:로

public static void SetWithMaxLength(ref string field, string value, int maxLength) 
{ 
    if(value.Length > maxLength) throw new Exception("Max length is " + maxLength); 
    field = value; 
} 

은 당신이 당신의 세터를 작성할 수

+0

나는이 질문을 올린 지 2 년이되었으며, 오늘은 여기서 내 질문을 검토하고 있습니다. 그때부터 C#을 배웠습니다. 지금은이 질문을하지 않겠습니다. 속성을 사용하여 유효성을 검사하지도 않았습니다. 약간의 노력을했기 때문에 답변을 수락 했으므로 SomeClass의 코드가 내 질문에 게시 한 것과 거의 똑같은 것을 지적하고 싶습니다. 또한 내부 속성 유효성 검사에 대한 경험이 있은 후 다시는이 작업을 수행하지 않으려 고합니다. 속성 내에서 예외를 throw하지 않을 것입니다. 그 이후로 내 마음이 완전히 바뀌었다. –

1

어셈블리, 유형, 멤버, 매개 변수 등의 메타 데이터를 다른 구성 요소, 도구, 컴파일러 등에 선언하는 것이 속성의 목적입니다. 물론 당신이 요구하는 것을 할 수는 있지만 그렇게해야합니다. 두 번째 예제에서와 같이 가치를 주장하기위한 먼 길입니다.

대신에 고려해야 할 사항은이 모든 것들이 내장되어 있으며 별도로 또는 외부 적으로 유효성을 검사 할 수있는 유효성 검사 프레임 워크입니다.

선택할 수있는 여러 가지 유효성 검사 프레임 워크가 있습니다. 내 머리 꼭대기에서 인기있는 두 가지는 FluentValidation이고 엔터프라이즈 라이브러리는 Validation Application Block입니다.

다른 한편으로는 좋은 Guard 클래스 또는 Code Contracts을 찾고있는 중일 것입니다. 이들은 유효성 검사와 다른 목적을 수행합니다 (Design by Contract 참조). 아마도 애트리뷰트를 결합하여 (Data Annotations을 재사용 할 것을 권장한다.) 어떤 aspect 지향 프로그래밍을 사용하면 선언적으로 가드를 처리 할 수있다. (PostSharp 참고). 그것은, 그러나, 아마 그냥 보여주는 것입니다 :). 당신이이 같은 물건을하지 않을 것입니다 일반적으로

set 
{ 
    SetWithMaxLength(ref this._someStr, value, 200); 
} 
+0

이 FluentValidation Framework는 흥미롭게 보이지만이 기본 유효성 검사를위한 프레임 워크를 사용하는 아이디어가 마음에 들지 않습니다 ...하지만 매우 흥미로운 것 같습니다 ... –

1

당신은 ref 매개 변수로 필드를 취하는 방법을 만들 수 속성이지만 권장할만한 것은 아니지만 가능합니다. 자신의 위험에 사용합니다 :) 제가 예를 확장 한 편집

public interface AttributeValidator 
    { 
     void CheckOk(object value); 
    } 

    public class LenghtAttribute : Attribute, AttributeValidator 
    { 
     public int MaxLength { get; private set; } 
     public LenghtAttribute(int lenght) 
     { 
      this.MaxLength = lenght; 
     } 

     public void CheckOk(object value) 
     { 
      var str = value as string; 
      if (str != value) 
       throw new Exception("Not a string!"); 

      if (str != null && str.Length > MaxLength) 
       throw new Exception("To long!"); 
     } 
    } 

    public class DoesNotContain : Attribute, AttributeValidator 
    { 
     public string Chars { get; private set; } 
     public DoesNotContain(string chars) 
     { 
      this.Chars = chars; 
     } 

     public void CheckOk(object value) 
     { 
      var str = value as string; 
      if (str != value) 
       throw new Exception("Not a string!"); 

      if (str != null && Chars.Any(c => str.Contains(c))) 
       throw new Exception("Contains forbidden character!"); 
     } 
    } 

    public class SomeClass 
    { 
     private string _someString; 

     [Lenght(200)] 
     [DoesNotContain("$#2")] 
     public string SomeString 
     { 
      get { return _someString; } 
      set 
      { 
       Utils.Validate("SomeString", this, value); 
       _someString = value; 
      } 
     } 
    } 

    public static class Utils 
    { 
     public static void Validate(string property, object instance, string value) 
     { 
      var validators = instance.GetType().GetProperty(property) 
       .GetCustomAttributes(false).OfType<AttributeValidator>(); 

      foreach (var validator in validators) 
       validator.CheckOk(value); 
     } 
    } 

(재산이 LengthAttribute : 장식되지 않은 경우 느슨한 지옥을하게됩니다). 여전히 끔찍한 해결책이지만 작동합니다.

+0

그래, ref 및 out 매개 변수에 대해 자세히 연구 할 수 있습니다 ... 감사합니다. ! –

관련 문제