Let us look at a cool AutoCAD .NET coding gadget in this post, which can copy all good properties from an AutoCAD Entity such as Circle to another which has different kind such as Line.
In the old days without the reflection technology, this is quite a nasty task. We generally had to cast the AutoCAD generic object/entity to each available good type and access to its properties. Many short points are with this approach. The two most prominent are not efficient at all likely hundreds of even thousands of line of code have to be made and not compatible with old or new object models so likely some properties are missing in one version but some others are not available in another.
With the wonderful reflection technology handy, all these problems have gone away completely. We can make the same work done more nicely and professionally in just about a dozen lines of code:
public static void BetweenDifferentKind(DBObject source, DBObject target)
{
if (source.GetType() == target.GetType())
throw new ArgumentException("The same kind!");
PropertyInfo[] piArr = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
PropertyInfo[] piArr1 = target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo pi in piArr)
{
PropertyInfo pi1 = piArr1.FirstOrDefault(p => p.Name == pi.Name && p.PropertyType == pi.PropertyType && p.CanRead && p.CanWrite);
if (pi.CanRead && pi.CanWrite && pi.PropertyType.Name != "Point3d" && pi1 != null)
{
try
{
pi1.SetValue(target, pi.GetValue(source, null), null);
}
catch (System.Reflection.TargetInvocationException tiEx)
{
Debug.WriteLine(tiEx.InnerException.Message); //ePlotStyleInColorDependentMode, etc.
}
}
}
}
public static void BetweenDifferentKind(ObjectId sourceId, ObjectId targetId)
{
if (sourceId.IsNull || targetId.IsNull || !sourceId.IsValid || !targetId.IsValid)
throw new ArgumentException();
using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
{
DBObject source = tr.GetObject(sourceId, OpenMode.ForRead) as DBObject;
DBObject target = tr.GetObject(targetId, OpenMode.ForWrite) as DBObject;
BetweenDifferentKind(source, target);
tr.Commit();
}
}
For the sake of convenience, the command used to test it has been appended below:
[CommandMethod("TestCopyProperties1")]
public static void TestCopyProperties1_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
try
{
PromptEntityResult selRes = ed.GetEntity("\nPick the source object:");
if (selRes.Status == PromptStatus.OK)
{
PromptEntityResult selRes1 = ed.GetEntity("\nPick the target object having a different kind:");
if (selRes1.Status == PromptStatus.OK)
{
CopyProperties.BetweenDifferentKind(selRes.ObjectId, selRes1.ObjectId);
}
}
}
catch (System.Exception ex)
{
ed.WriteMessage(ex.ToString());
}
}
If a Circle and a Line are selected for example, the properties of the Circle will be copied over to the Line including not only some general information like layer, color, linetype and line weight but also some complex properties like material and shadow display. The geometry properties with the Point3d type have been excluded from the case since we do not want to change the Line geometry.
If the Circle and the Line look like the following before properties being copied:
The properties of the Line will match with those of the Circle after properties being copied over as can be seen from the following image:
So, the code can be used to copy properties from an AutoCAD Entity to another in case they have different kinds without modifications or be tailored to suit other needs. Enjoy it! More coding gadgets will be created and demonstrated in the future. Please stay tuned.
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides various project wizards, item wizards, coders and widgets to help program AutoCAD .NET addins.
Posted by: |