雪山飞狐_lzh 发表于 2010-1-4 14:31:00

ResultBuffer简化类

本帖最后由 作者 于 2010-7-9 18:30:24 编辑

经常要做些选择集的过滤器,然而.Net的过滤器写起来真的很繁琐
所以。。。
ResultList类,原创是TonyT,:)
using System;
using System.Collections.Generic;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
namespace TlsCad.Collections
{
    /// <summary>
    /// TypedValue Collection
    /// </summary>
    public class ResultList : List<TypedValue>, IFormattable
    {
      public ResultList(){ }
      public ResultList(IEnumerable<TypedValue> values) : base(values)
      { }
      public ResultList(ResultBuffer rb) : base(rb.AsArray())
      { }
      #region Add
      public void Add(int typeCode, object obj)
      {
            base.Add(new TypedValue(typeCode, obj));
      }
      public void Add(LispDataType type, object obj)
      {
            base.Add(new TypedValue((int)type, obj));
      }
      public void Add(DxfCode type, object obj)
      {
            base.Add(new TypedValue((int)type, obj));
      }
      #endregion
      #region Convert
      public static implicit operator TypedValue[](ResultList rlst)
      {
            return rlst.ToArray();
      }
      public static implicit operator ResultBuffer(ResultList rlst)
      {
            return new ResultBuffer(rlst.ToArray());
      }
      public static implicit operator SelectionFilter(ResultList rlst)
      {
            return new SelectionFilter(rlst.ToArray());
      }
      #endregion
      #region IFormattable 成员
      public override string ToString()
      {
            var rb = new ResultBuffer(ToArray());
            return rb.ToString();
      }
      string IFormattable.ToString(string format, IFormatProvider formatProvider)
      {
            var rb = new ResultBuffer(ToArray());
            return rb.ToString(format, formatProvider);
      }
      #endregion
    }
}


ResultTree类,原创飞狐
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using System.Collections;
namespace TlsCad.Collections
{
   
    public enum ResultTreeType
    {
      Node,
      List,
      DottedPair,
      RelationalOperator,
      LogicalOperator,
    }
   
    /// <summary>
    /// TypedValue Tree
    /// </summary>
    public class ResultTree : IEnumerable<ResultTree>, IFormattable
    {
      ResultTreeType _treeType;
      ResultTree _owner;
      TypedValue _typedValue;
      List<ResultTree> _lst = new List<ResultTree>();
      static readonly List<string> _relationalOperatorNames =
            new List<string> { "not", "and", "or", "xor" };
      #region Properties
      public ResultTree this
      {
            get
            {
                if (_lst.Count == 0)
                {
                  if(index == 0)
                  {
                        return this;
                  }
                }
                else
                {
                  if (index >= 0 && index < _lst.Count)
                  {
                        return _lst;
                  }
                }
                return null;
            }
      }
      public ResultTreeType TreeType
      {
            get { return _treeType; }
      }
      public TypedValue TypedValue
      {
            get { return _typedValue; }
      }
      public short TypeCode
      {
            get { return _typedValue.TypeCode; }
      }
      public LispDataType LispDataType
      {
            get { return (LispDataType)TypeCode; }
      }
      public DxfCode DxfCode
      {
            get { return (DxfCode)TypeCode; }
      }
      public object Value
      {
            get { return _typedValue.Value; }
      }
      public T GetValue<T>()
      {
            return (T)_typedValue.Value;
      }
      #endregion
      #region Constructor
      public ResultTree()
      {
            _treeType = ResultTreeType.Node;
      }
      public ResultTree(TypedValue value)
            :this()
      {
            _typedValue = value;
      }
      public ResultTree(int typeCode, object obj)
            : this(new TypedValue(typeCode, obj))
      { }
      public ResultTree(LispDataType type, object obj)
            : this(new TypedValue((int)type, obj))
      { }
      public ResultTree(DxfCode type, object obj)
            : this(new TypedValue((int)type, obj))
      { }

      public ResultTree(string operatorContext)
      {
            operatorContext = operatorContext.ToLower();
            _treeType =
                _relationalOperatorNames.Contains(operatorContext) ?
                ResultTreeType.RelationalOperator : ResultTreeType.LogicalOperator;
            _typedValue = new TypedValue(-4, operatorContext);
      }
      public ResultTree(ResultTreeType type)
      {
            _treeType = type;
      }
      private enum ResultNodeType
      {
            Node,
            ListBegin,
            ListEnd,
            DottedPairEnd,
            LogicalOperator,
            RelationalOperatorBegin,
            RelationalOperatorEnd,
      }
      private ResultNodeType GetNodeType(TypedValue tvalue, out ResultTree rt)
      {
            short typeCode = tvalue.TypeCode;
            object value = tvalue.Value;
            rt = null;
            
            if (typeCode == -4)
            {
                string s = ((string)value).ToLower();
                if(s == '<' && _relationalOperatorNames.Contains(s.Substring(1)))
                {
                  rt = new ResultTree(s.Substring(1));
                  return ResultNodeType.RelationalOperatorBegin;
                }
                else if(s == '>' && _relationalOperatorNames.Contains(s.Substring(0, s.Length - 1)))
                {
                  return ResultNodeType.RelationalOperatorEnd;
                }
                else
                {
                  rt = new ResultTree(s);
                  return ResultNodeType.LogicalOperator;
                }
            }
            else if(typeCode == (short)LispDataType.ListBegin)
            {
                rt = new ResultTree(ResultTreeType.List);
                return ResultNodeType.ListBegin;
            }
            else if(typeCode == (short)LispDataType.ListEnd)
            {
                return ResultNodeType.ListEnd;
            }
            else if(typeCode == (short)LispDataType.DottedPair)
            {
                return ResultNodeType.DottedPairEnd;
            }
            else
            {
                rt = new ResultTree(tvalue);
                return ResultNodeType.Node;
            }
      }
      public ResultTree(ResultBuffer rb)
      {
            ResultTree rt = this;
            foreach (TypedValue tv in rb)
            {
                ResultTree trt;
                switch (GetNodeType(tv, out trt))
                {
                  case ResultNodeType.LogicalOperator:
                  case ResultNodeType.RelationalOperatorBegin:
                  case ResultNodeType.ListBegin:
                        rt = rt.Add(trt);
                        break;
                  case ResultNodeType.DottedPairEnd:
                        rt._treeType = ResultTreeType.DottedPair;
                        rt = rt._owner;
                        break;
                  case ResultNodeType.RelationalOperatorEnd:
                  case ResultNodeType.ListEnd:
                        rt = rt._owner;
                        break;
                  default:
                        rt.Add(trt);
                        if (rt._treeType == ResultTreeType.RelationalOperator)
                            rt = rt._owner;
                        break;
                }
            }
            if (_lst.Count == 1)
            {
                rt = _lst;
                _lst.Remove(rt);
                _lst.AddRange(rt);
                _treeType = rt._treeType;
                _typedValue = rt._typedValue;
            }
      }
      #endregion
      #region Set
      public void Set(int typeCode, object obj)
      {
            _typedValue = new TypedValue(typeCode, obj);
      }
      public void Set(LispDataType type, object obj)
      {
            _typedValue = new TypedValue((int)type, obj);
      }
      public void Set(DxfCode type, object obj)
      {
            _typedValue = new TypedValue((int)type, obj);
      }

      public void Set(int typeCode)
      {
            _typedValue = new TypedValue(typeCode);
      }
      public void Set(LispDataType type)
      {
            _typedValue = new TypedValue((int)type);
      }
      public void Set(DxfCode type)
      {
            _typedValue = new TypedValue((int)type);
      }
      #endregion
      #region Add
      public ResultTree Add(TypedValue value)
      {
            return Add(new ResultTree(value));
      }
      public ResultTree Add(int typeCode, object obj)
      {
            return Add(new ResultTree(typeCode, obj));
      }
      public ResultTree Add(LispDataType type, object obj)
      {
            return Add(new ResultTree(type, obj));
      }
      public ResultTree Add(DxfCode type, object obj)
      {
            return Add(new ResultTree(type, obj));
      }
      public ResultTree Add(ResultTree rt)
      {
            rt._owner = this;
            _lst.Add(rt);
            return rt;
      }
      #region Add LispData
      public ResultTree Add(short value)
      {
            return Add(new ResultTree(LispDataType.Int16, value));
      }
      public ResultTree Add(int value)
      {
            return Add(new ResultTree(LispDataType.Int32, value));
      }
      public ResultTree Add(double value)
      {
            return Add(new ResultTree(LispDataType.Double, value));
      }
      public ResultTree Add(string value)
      {
            return Add(new ResultTree(LispDataType.Text, value));
      }
      public ResultTree Add(Point2d value)
      {
            return Add(new ResultTree(LispDataType.Point2d, value));
      }
      public ResultTree Add(Point3d value)
      {
            return Add(new ResultTree(LispDataType.Point3d, value));
      }
      public ResultTree Add(ObjectId value)
      {
            return Add(new ResultTree(LispDataType.ObjectId, value));
      }
      public ResultTree Add(SelectionSet value)
      {
            return Add(new ResultTree(LispDataType.SelectionSet, value));
      }
      //public void Add(ResultType type, params object[] values)
      //{
      //    ResultTree rt = new ResultTree(type);
      //    foreach (object value in values)
      //    {
      //      if (value is short)
      //      {
      //            rt.Add((short)value);
      //      }
      //      else if (value is int)
      //      {
      //            rt.Add((int)value);
      //      }
      //      else if (value is double)
      //      {
      //            rt.Add((double)value);
      //      }
      //      else if (value is string)
      //      {
      //            rt.Add((string)value);
      //      }
      //      else if (value is Point2d)
      //      {
      //            rt.Add((Point2d)value);
      //      }
      //      else if (value is Point3d)
      //      {
      //            rt.Add((Point3d)value);
      //      }
      //      else if (value is ObjectId)
      //      {
      //            rt.Add((ObjectId)value);
      //      }
      //      else if (value is SelectionSet)
      //      {
      //            rt.Add((SelectionSet)value);
      //      }
      //    }
      //}
      #endregion
      #endregion
      #region Convert
      private void GetValues(List<TypedValue> values)
      {
            switch (_treeType)
            {
                caseResultTreeType.Node:
                  if (_lst.Count == 0)
                  {
                        values.Add(_typedValue);
                  }
                  else
                  {
                        _lst.ForEach(rtree => rtree.GetValues(values));
                  }
                  break;
                case ResultTreeType.List:
                  values.Add(new TypedValue((int)LispDataType.ListBegin));
                  _lst.ForEach(rtree => rtree.GetValues(values));
                  values.Add(new TypedValue((int)LispDataType.ListEnd));
                  break;
                case ResultTreeType.DottedPair:
                  values.Add(new TypedValue((int)LispDataType.ListBegin));
                  _lst.ForEach(rtree => rtree.GetValues(values));
                  values.Add(new TypedValue((int)LispDataType.DottedPair));
                  break;
                case ResultTreeType.LogicalOperator:
                  values.Add(_typedValue);
                  _lst.ForEach(rtree => rtree.GetValues(values));
                  break;
                case ResultTreeType.RelationalOperator:
                  values.Add(new TypedValue(-4, "<" + _typedValue.Value));
                  _lst.ForEach(rtree => rtree.GetValues(values));
                  values.Add(new TypedValue(-4, _typedValue.Value + ">"));
                  break;
            }
      }
      public TypedValue[] ToArray()
      {
            List<TypedValue> values = new List<TypedValue>();
            GetValues(values);
            return values.ToArray();
      }
      public static implicit operator SelectionFilter(ResultTree rtree)
      {
            return new SelectionFilter(rtree.ToArray());
      }
      public static implicit operator ResultBuffer(ResultTree rtree)
      {
            return new ResultBuffer(rtree.ToArray());
      }
      #endregion
      #region RelationalOperator
      private void MakeRelationalOperator(string operatorContext, ResultTree res)
      {
            if (_treeType == ResultTreeType.RelationalOperator && _typedValue.Value.ToString() == operatorContext)
            {
                res._lst.AddRange(_lst);
            }
            else
            {
                res.Add(this);
            }
      }
      public static ResultTree operator !(ResultTree rt1)
      {
            ResultTree rt = new ResultTree("not") { rt1 };
            return rt;
      }
      public static ResultTree operator &(ResultTree rt1, ResultTree rt2)
      {
            ResultTree rt = new ResultTree("and");
            rt1.MakeRelationalOperator("and", rt);
            rt2.MakeRelationalOperator("and", rt);
            return rt;
      }
      public static ResultTree operator |(ResultTree rt1, ResultTree rt2)
      {
            ResultTree rt = new ResultTree("or");
            rt1.MakeRelationalOperator("or", rt);
            rt2.MakeRelationalOperator("or", rt);
            return rt;
      }
      public static ResultTree operator ^(ResultTree rt1, ResultTree rt2)
      {
            return
                new ResultTree("xor")
                {
                  rt1,
                  rt2
                };
      }
      #endregion
      
      #region IFormattable 成员
      public override string ToString()
      {
            var rb = new ResultBuffer(ToArray());
            return rb.ToString();
      }
      string IFormattable.ToString(string format, IFormatProvider formatProvider)
      {
            var rb = new ResultBuffer(ToArray());
            return rb.ToString(format, formatProvider);
      }
      #endregion
      #region IEnumerable<ResultTree> 成员
      #region IEnumerable 成员
      IEnumerator IEnumerable.GetEnumerator()
      {
            return _lst.GetEnumerator();
      }
      #endregion
      IEnumerator<ResultTree> IEnumerable<ResultTree>.GetEnumerator()
      {
            return _lst.GetEnumerator();
      }
      #endregion
    }
}


扩展方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TlsCad.Collections;
using Autodesk.AutoCAD.DatabaseServices;
namespace TlsCad.ExtendMethods
{
    public static class ResultBufferEx
    {
      public static ResultList ToList(this ResultBuffer rb)
      {
            return new ResultList(rb);
      }
      public static ResultTree ToTree(this ResultBuffer rb)
      {
            return new ResultTree(rb);
      }
    }
}



示例代码      
      public static void Test9()
      {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptSelectionResult res1 =
                ed.SelectAll(
                  new ResultTree
                  {
                        new ResultTree(">,>,*")
                        {
                            {10, new Point3d()}
                        },
                        new ResultTree("<,<,*")
                        {
                            {10, new Point3d(10,10,0)}
                        }
                  });
            PromptSelectionResult res2 =
                ed.SelectAll(
                  new ResultList
                  {
                        {-4, ">,>,*"},
                        {10, new Point3d()},
                        {-4, "<,<,*"},
                        {10, new Point3d(10,10,0)}
                  });

            PromptSelectionResult res3 =
                ed.SelectAll(
                  new ResultTree("or")
                  {
                        new ResultTree("and")
                        {
                            {0, "Line"},
                            {8, "01"}
                        },
                        new ResultTree("and")
                        {
                            {0, "Circle"},
                            {8, "02"}
                        }
                  });
            PromptSelectionResult res4 =
                ed.SelectAll(
                  new ResultList
                  {
                        {-4, "<or"},
                            {-4, "<and"},
                              {0, "Line"},
                              {8, "01"},
                            {-4, "and>"},
                            {-4, "<and"},
                              {0, "Circle"},
                              {8, "02"},
                            {-4, "and>"},
                        {-4, "or>"}
                  });

      }
      
      public static void Test10()
      {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptEntityResult res = ed.GetEntity("Select a Entity:");
            using (DBTransaction tr = new DBTransaction())
            {
                tr.OpenRegAppTable(OpenMode.ForWrite);
                tr.RegApp("MyApp");
                Entity ent = tr.GetObject(res.ObjectId, OpenMode.ForWrite) as Entity;
                ent.XData =
                  new ResultList
                  {
                        {1001, "MyApp"},
                        {1000, "This is a Test"},
                        {DxfCode.ExtendedDataInteger16, 12}
                  };
            }
      }
      
      public static void Test11()
      {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptEntityResult res1 = ed.GetEntity("\nSelect a Entity:");
            InvokeArx.CmdEcho = false;
            InvokeArx.Command(
                false,
                new ResultTree
                {
                  "break",
                  new ResultTree(ResultType.List)
                  {
                        res1.ObjectId,
                        res1.PickedPoint
                  },
                  res1.PickedPoint
                });
            InvokeArx.CmdEcho = true;
      }
      
      public static ResultBuffer LTest1(ResultBuffer rb)
      {
            ResultTree rtree =
                new ResultTree(ResultType.List)
                {
                  1,
                  new ResultTree(ResultType.DottedPair)
                  {
                        10,
                        new Point3d(10, 10, 0)
                  }
                };
            return rtree;
      }

雪山飞狐_lzh 发表于 2010-1-4 14:33:00

不过,简化写法必须在VS2008及以上版本才支持

雪山飞狐_lzh 发表于 2010-1-4 21:24:00

ResultTree的操作符重载版本(一楼代码已更改),这样写挺好玩的,:)
测试代码
            ResultTree rt =
                new ResultTree(0, "Line") & new ResultTree(8, "01") & !new ResultTree(10, new Point3d())
                |
                new ResultTree(0, "Circle") & new ResultTree(8, "02");
            ed.WriteMessage(rt.ToString());返回:
((-4,<or)(-4,<and)(0,Line)(8,01)(-4,<not)(10,(0,0,0))(-4,not>)(-4,and>)(-4,<and)
(0,Circle)(8,02)(-4,and>)(-4,or>))


游天居士 发表于 2010-1-4 21:36:00

个人觉得还是太麻烦。实际可能少用到。我就没有这样用过。

single-yu 发表于 2010-1-4 21:37:00

<p>顶我们的狐老大,哈哈!</p>

雪山飞狐_lzh 发表于 2010-7-9 15:53:00

本帖最后由 作者 于 2010-7-9 18:44:37 编辑

更新版本,增加与ResultBuffer的互相转换,增强Lisp相关操作
简化选择集中逻辑表达式的写法(见示例)

LispFunction的相关示例


      
      public object lsptest11(ResultBuffer rb)
      {
            ResultTree rt = rb.ToTree();
            switch (rt.TreeType)
            {
                case ResultTreeType.Node:
                  switch (rt.LispDataType)
                  {
                        case LispDataType.Point2d:
                            Point2d pt2d = rt.GetValue<Point2d>();
                            rt.Set(LispDataType.Point2d, new Point2d(10, pt2d.Y));
                            break;
                        case LispDataType.Point3d:
                            Point3d pt3d = rt.GetValue<Point3d>();
                            rt.Set(LispDataType.Point3d, new Point3d(10, pt3d.Y, pt3d.Z));
                            break;
                  }
                  break;
                case ResultTreeType.List:
                case ResultTreeType.DottedPair:
                  rt.Set(LispDataType.Int16, 10);
                  return (ResultBuffer)rt;
            }
            return rt.TypedValue;
      }


效果:

命令: (mylisp1 '(1 2))
(10.0 2.0)
命令: (mylisp1 '(1 2 3))
(10.0 2.0 3.0)
命令: (mylisp1 '(1 2 3 4))
(10 2 3 4)
命令: (mylisp1 3)
3

Student 发表于 2010-7-13 22:01:00

<p>&nbsp;好。</p>

Rain_Franklin 发表于 2010-8-24 17:32:00

必须留言 .... 好东西呀

arxnew 发表于 2010-10-2 15:35:00

<p>好东西,学习中</p>

河伯 发表于 2011-1-24 10:01:11

lisp传递参数的ResultBuffer,有时表被当成点对,如何解决?

//Lisp:第二个参数是四个整数
(TTT "AAA" (list 10 20 30 40) 12.36)

//.NET:把(list 10 20 30 40)当成点对,得到一个Point3D(20,30,40),显然不对
<LispFunction("TTT")> Public Sub TTT(ByVal rbArgs As ResultBuffer)
   'rbArgs
End Sub
页: [1] 2 3
查看完整版本: ResultBuffer简化类