NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 학습
  • 매뉴얼

    학습


    C# C# .NET 매크로 프로그램 만들기. (좌표 연산)

    페이지 정보

    본문

    안녕하세요. 엔지엠소프트웨어입니다. 오늘부터 좌표 연산, 크기 연산, 사각형 연산을 하나씩 만들어 볼텐데요. 이 액션들은 특별히 로직이랄게 없습니다. 코드도 단순하거든요. 그리고, 좌표와 크기, 사각형은 동일합니다. 개체 형식만 다를뿐입니다. 좌표는 Point고, 크기는 Size입니다. 사각형은 Rectangle입니다.

     

    액션 모델들은 미리 만들어 놓는게 좋겠네요.

    yoEMXDO.jpeg

     

     

    항상 그렇듯이 클래스는 BaseModel을 상속 받고, 속성들을 추가해줘야 합니다.

    public class PointFormulaModel : BaseModel

     

    사용자에게 처리 결과를 보여줄 Data 속성들을 만듭니다.

    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ObjectResult")]
    [LocalizedDescription("ObjectResult")]
    [Browsable(true)]
    [DefaultValue(null)]
    public Point? ObjectResult { get; set; }
    
    [LocalizedCategory("Data")]
    [LocalizedDisplayName("X")]
    [LocalizedDescription("X")]
    [Browsable(true)]
    [DefaultValue(null)]
    public int? X { get; set; }
    
    [LocalizedCategory("Data")]
    [LocalizedDisplayName("Y")]
    [LocalizedDescription("Y")]
    [Browsable(true)]
    [DefaultValue(null)]
    public int? Y { get; set; }

     

    아래는 2개의 좌표를 어떻게 연산할지 사용자가 선택하는 옵션들입니다.

    [LocalizedCategory("Action")]
    [LocalizedDisplayName("Operator")]
    [LocalizedDescription("Operator")]
    [Browsable(true)]
    [DefaultValue(typeof(Ai.Definition.Operator), "Plus")]
    public Ai.Definition.Operator Operator { get; set; } = Definition.Operator.Plus;
    
    [LocalizedCategory("Action")]
    [LocalizedDisplayName("FormulaOption")]
    [LocalizedDescription("FormulaOption")]
    [Browsable(true)]
    [DefaultValue(typeof(Ai.Definition.PointFormulaOption), "All")]
    public Ai.Definition.PointFormulaOption Option { get; set; } = Definition.PointFormulaOption.All;

     

    Operator는 사칙연산을 나타내는데요. 실제로 내부는 아래와 같이 되어 있습니다.

    public enum Operator
    {
        Plus = 0,
        Minus = 1,
        Divide = 2,
        Multiply = 3
    }

     

    Option은 개체 형식에서 제공하는 X와 Y에서 어떤 값만 처리할지를 결정하도록 합니다. 물론, XY 둘다 연산할수도 있습니다.

    public enum PointFormulaOption
    {
        All = 0,
        X = 1, 
        Y = 2
    }


    처리로직은 여러분들이 생각하는 그 방법입니다. 단순 무식하게 처리하고 있는데요. 이 방법이 가장 간단한 방법이기도 합니다. 그리고, Point type은 X와 Y로 이루어진 구조체인데요. 재정의된 ToString을 보면 X=100, Y=100과 같이 속성에 문자가 할당됩니다. 그리고, 개체를 표시하는 컬리 브래킷({ })으로 감싸고 있습니다.

    public override string? Execute(IPlayer player)
    {
        ObjectResult = null;
        var id = base.Execute(player);
    
        var lv = Ai.Common.Helper.GetMatches(player, this.GetType().GetProperty(nameof(LeftValue)), LeftValue);
        var rv = Ai.Common.Helper.GetMatches(player, this.GetType().GetProperty(nameof(RightValue)), RightValue);
    
        var leftValue = System.Windows.Point.Parse(Regex.Replace(lv, @"[^0-9,]", ""));
        var rightValue = System.Windows.Point.Parse(Regex.Replace(rv, @"[^0-9,]", ""));
    
        switch (Operator)
        {
            case Definition.Operator.Plus:
                switch (Option)
                {
                    case Definition.PointFormulaOption.All:
                        ObjectResult = new Point((int)(leftValue.X + rightValue.X), (int)(leftValue.Y + rightValue.Y));
                        break;
                    case Definition.PointFormulaOption.X:
                        ObjectResult = new Point((int)(leftValue.X + rightValue.X), (int)leftValue.Y);
                        break;
                    case Definition.PointFormulaOption.Y:
                        ObjectResult = new Point((int)leftValue.X, (int)(leftValue.Y + rightValue.Y));
                        break;
                }
                break;
            case Definition.Operator.Minus:
                switch (Option)
                {
                    case Definition.PointFormulaOption.All:
                        ObjectResult = new Point((int)(leftValue.X - rightValue.X), (int)(leftValue.Y - rightValue.Y));
                        break;
                    case Definition.PointFormulaOption.X:
                        ObjectResult = new Point((int)(leftValue.X - rightValue.X), (int)leftValue.Y);
                        break;
                    case Definition.PointFormulaOption.Y:
                        ObjectResult = new Point((int)leftValue.X, (int)(leftValue.Y - rightValue.Y));
                        break;
                }
                break;
            case Definition.Operator.Multiply:
                switch (Option)
                {
                    case Definition.PointFormulaOption.All:
                        ObjectResult = new Point((int)(leftValue.X * rightValue.X), (int)(leftValue.Y * rightValue.Y));
                        break;
                    case Definition.PointFormulaOption.X:
                        ObjectResult = new Point((int)(leftValue.X * rightValue.X), (int)leftValue.Y);
                        break;
                    case Definition.PointFormulaOption.Y:
                        ObjectResult = new Point((int)leftValue.X, (int)(leftValue.Y * rightValue.Y));
                        break;
                }
                break;
            case Definition.Operator.Divide:
                switch (Option)
                {
                    case Definition.PointFormulaOption.All:
                        ObjectResult = new Point((int)(leftValue.X / rightValue.X), (int)(leftValue.Y / rightValue.Y));
                        break;
                    case Definition.PointFormulaOption.X:
                        ObjectResult = new Point((int)(leftValue.X / rightValue.X), (int)leftValue.Y);
                        break;
                    case Definition.PointFormulaOption.Y:
                        ObjectResult = new Point((int)leftValue.X, (int)(leftValue.Y / rightValue.Y));
                        break;
                }
                break;
        }
    
        if (ObjectResult.HasValue)
        {
            X = ObjectResult.Value.X;
            Y = ObjectResult.Value.Y;
            Result = ObjectResult.Value.ToString();
        }
    
        return id;
    }

     

    개발자라면 Json은 모두 알고 있을건데요. Point를 ToString으로 가져오면 Json으로 변환해서 다시 오브젝트로 바꿀 수 있습니다. 일반적으로 Serialize, Deserialize라고 부릅니다. 개체를 직렬화하면 파일로 저장할 수 있고, 역직렬화하면 파일을 메모리 공간의 개체로 복구할 수 있습니다. 데이타 전송에도 사용할 수 있습니다.

     

    매크로를 실행하고, 실제 연산이 되는지 테스트 해볼까요?

    uvIjMZ2.jpeg

     

     

    대부분의 프로그래밍 언어들이 비슷하겠지만, 닷넷은 오브젝트 형식을 어떻게 처리할지에 대해서 고민이 많은 언어입니다. 일반적으로는 이런식으로 프로그래밍을 하지 않는데요. 사용자와 상호작용해야 하는 클라이언트 프로그램들은 어쩔 수 없는 부분이기도 합니다. 최적화를 어떻게 해야 할지에 대해서 많은 고민이 필요하고, 수많은 타입에 대해 모두 날코딩으로 처리하기에도 부담이 매우 큽니다.

     

    다행스럽게도 닷넷은 object로 박싱된 개체라도 GetType을 통해 언더링 타입을 알아낼 수 있습니다. 전통적인 닷넷에서 없었던 Generic과 Nullable이 추가되면서 문제를 해결하는데 더 복잡해졌습니다. 모든 형식은 Nullable로 감쌀 수 있는데요. 하필이면 이 형식이 Generic에서 파생된다는 점입니다. Generic은 IList, ICollection등등... 목록형도 포함하고 있기 때문에 단수 형식의 제네릭과 복수 형식의 제네릭을 처리하는데 구분이 필요합니다.

     

    개발자에게 후원하기

    MGtdv7r.png

     

    추천, 구독, 홍보 꼭~ 부탁드립니다.

    여러분의 후원이 빠른 귀농을 가능하게 해줍니다~ 답답한 도시를 벗어나 귀농하고 싶은 개발자~

    감사합니다~

    • 네이버 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 카카오스토리 공유하기
    추천0 비추천0

    댓글목록

    등록된 댓글이 없습니다.