문제

나는 C# (지난 주에 시작)을 처음 접 했으니 나와 함께 시원해;). 어떻게 든 사용자 정의 속성을 쓸 수 있는지 알고 싶습니다. 설명하겠습니다.

속성을 추가하여 완료 한 부분 클래스가 있지만 모든 게터와 세터의 패턴은 동일하므로 이것을 고려하고 싶습니다.

public partial class Travel
{
    public String TravelName
    {
        get
        {
            return LocaleHelper.GetRessource(Ressource1);
        }
        set
        {
            if (this.Ressource1 == null)
                Ressource1 = new Ressource() { DefaultValue = value };
            else
                Ressource1.DefaultValue = value;
        }
    }

    public String TravelDescription
    {
        get
        {
            return LocaleHelper.GetRessource(Ressource2);
        }
        set
        {
            if (this.Ressource2 == null)
                Ressource2 = new Ressource() { DefaultValue = value };
            else
                Ressource2.DefaultValue = value;
        }
    }
}

보시다시피, 변화하는 유일한 것은 ressource1/ressource2입니다. 내 목표는 다음과 같은 것을 쓸 수 있다는 것입니다.

public partial class Travel
{
    public LocalizedString TravelName(Ressource1);

    public LocalizedString TravelDescription(Ressource2);
}

누구든지 이것을 만들어야 할 아이디어가 있습니까? 아니면 내 코드를 청정하게 만드는 다른 아이디어가 있습니까? 고맙습니다,

기 illa

도움이 되었습니까?

해결책

C# 또는 .NET 자체 내부 에서이 작업을 수행 할 시설은 없지만이 작업을 많이 수행하는 경우 측면 지향 프로그래밍을 조사하는 것이 좋습니다. 포스트 쇼트. 기본적으로 컴파일 시간에 추가 코드를 주입하는 속성을 정의 할 수 있습니다. 입력 한 코드는 다음과 같습니다.

public partial class Travel
{
    [LocalizedProperty(source = "Ressource1")
    public string TravelName { get; set; }

    [LocalizedProperty(source = "Ressource2")
    public string TravelDescription{ get; set; }
}

그리고 Compile Time에서 PostSharp는이 속성을 새로운 LocalizedPropertyAttribute 클래스에서 정의한 템플릿으로 대체합니다.

다른 팁

당신은 그것을 만들 수 없습니다 상당히 설명하는 것만 큼 간결하지만 세터의 복잡성과 중복성을 줄일 수 있습니다.

private void SetRessource(ref Ressource res, string value)
{
    if(res == null) res = new Ressource();

    res.DefaultValue = value;
}

public String TravelName
{
    get { return LocaleHelper.GetRessource(Ressource1); }
    set { SetRessource(ref this.Ressource1, value); }
}

public String TravelDescription
{
    get { return LocaleHelper.GetRessource(Ressource2); }
    set { SetRessource(ref this.Ressource2, value); }
}

나는 당신이 무엇을 달성하려고하는지 정확히 알지 못하지만, 당신은 너무 복잡하게 만들 수 있습니다. 이것이 충분하지 않습니까?

public class Travel
{
   /// <summary>
   /// Creates a new instance of <see cref="Travel"/>.
   /// </summary>
   public Travel()
   {
      this.TravelName = Resources.DefaultTravelName;
      this.TravelDescription = Resources.DefaultTravelDescription;
   }

   public string TravelName { get; set; }

   public string TravelDescription { get; set; }
}

여기서 리소스는 현지화 된 자원에 대한 생성 클래스 (Resx 파일)입니다. 나는 당신이 아직 .NET를 모르기 때문에 자신의 현지화 프레임 워크를 구축하려는 느낌이 있습니다. 이미 인프라가 있습니다.

아니요, 그런 방법이 없습니다. 그럴 것입니다 PHP에서 가능합니다 그러나 C#은 아닙니다.

이 경우에는 접근 방식을 속성에서 멀리 변경해야합니다.

UPD : 아마도 모든 속성에 이와 같은 것을 사용할 수있을 것입니다 (명백한 약점을 제외하고) :

public class Prop
{
    Resource _res;

    public Prop(Resource res)
    {
        this._res = res;
    }

    public string Value
    {
        get
        {
            return LocaleHelper.GetRessource(_res);
        }
        set
        {
            if(_res == null)
                // This is a weak point as it's now
                // as it wont work
            else
                _res.DefaultValue = value;
        }
}

단일 인덱스 속성을 구현하여 선호도에 따라 다음 두 개의 구문 선택 중 하나를 제공 할 수 있습니다. 코드는 기본적으로 특별히 명명 된 리소스를 받아들이고 올바른 컨텐츠를 반환하는 함수입니다.

Travel t = new Travel();
string x = t["Name"];
    or 
string x = t[Travel.Name];

기본 클래스에서 getter 및 setter logic을 캡슐화 한 다음 작성한 새로운 속성에서 해당 방법을 호출하여 인생을 더 쉽게 만들 수 있습니다 (단순히 해당 메소드 주위의 얇은 래퍼 역할을합니다). 예는 다음과 같습니다.

public class Travel : LocalizedRessourceSubscriber
{

    private Ressource<string> Ressource1 = null;
    private Ressource<string> Ressource2 = null;

    public String TravelName { 
        get { return GetRessource<string>(Ressource2); }
        set { SetRessource<string>(Ressource1, value); } 
    }

    public String TravelDescription {
        get { return GetRessource<string>(Ressource2); }
        set { SetRessource<string>(Ressource2, value); } 
    }

}

public class LocalizedRessourceSubscriber
{

    protected T GetRessource<T>(Ressource<T> Source)
    {
        return LocaleHelper.GetRessource<T>(Source);
    }

    protected void SetRessource<T>(Ressource<T> Source, T Value)
    {
       (Source ?? 
           (Source = new Ressource<T>())
                ).DefaultValue = Value;
    }

}

... 이런 식으로, 속성에는 논리가 거의 없으며 코드를 덜 반복하고 있습니다. 이것은 다음 클래스를 가정합니다 (일반화 된대로 조롱 한).

public static class LocaleHelper
{
    public static T GetRessource<T>(Ressource<T> Source)
    {
        return default(T);
    }
}

public class Ressource<T>
{
    public T DefaultValue { get; set; }
}

그것은 말이되지 않습니다. 속성을 사용하여 현재 가지고있는 방식은 다음과 같이 간단히 쓸 수 있습니다.

   Travel t = new Travel();
   string tvlName = t.TravelName;    
   string desc = t.TravelDescription;

원하는 방식으로 변경되면 매개 변수도 지정해야합니다.

   Travel t = new Travel();
   LocalizedString tvlName = t.TravelName([someresopurcedesignator]);    
   LocalizedString desc = t.TravelDescription([someresopurcedesignator]);  

당신이 할 수있는 것은 "Propertybag"에뮬레이터를 만드는 것뿐입니다.

   public class Travel 
   {
       private LocalizedString props = new LocalizedString();
       public LocalizedString Propertys
       {
          get { return props; }
          set { props = value; }
       }

   }

   public class LocalizedString // this is property Bag emulator
   {
       public string this[string resourceName]
       {
           get{ return LocaleHelper.GetRessource(resourceName); }
           set{ LocaleHelper.GetRessource(resourceName) = value; }
       }
   }

다음과 같이 액세스 할 수 있습니다.

   Travel t = new Travel();
   t.Propertys[NameResource1] = "Bob Smith";
   t.Propertys[DescriptionResource2] = "Fun trip to discover the orient";
   string tvlName = t.Propertys[NameResource1];    
   string desc    = t.Propertys[DescriptionResource2];    
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top