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;
}
不过,简化写法必须在VS2008及以上版本才支持 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>))
个人觉得还是太麻烦。实际可能少用到。我就没有这样用过。 <p>顶我们的狐老大,哈哈!</p> 本帖最后由 作者 于 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
<p> 好。</p> 必须留言 .... 好东西呀 <p>好东西,学习中</p> 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