• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DomCR / ACadSharp / 18679832337

21 Oct 2025 09:46AM UTC coverage: 77.883% (-0.2%) from 78.126%
18679832337

push

github

web-flow
Merge pull request #832 from DomCR/multileader-dxf

multileader dxf

6920 of 9695 branches covered (71.38%)

Branch coverage included in aggregate %.

341 of 429 new or added lines in 16 files covered. (79.49%)

77 existing lines in 8 files now uncovered.

26664 of 33426 relevant lines covered (79.77%)

110330.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

54.94
/src/ACadSharp/DxfPropertyBase.cs
1
using ACadSharp.Attributes;
2
using ACadSharp.Objects;
3
using CSMath;
4
using CSUtilities.Converters;
5
using CSUtilities.Extensions;
6
using System;
7
using System.Collections;
8
using System.Linq;
9
using System.Reflection;
10

11
namespace ACadSharp
12
{
13
        public abstract class DxfPropertyBase<T>
14
                where T : Attribute, ICodeValueAttribute
15
        {
16
                public DxfReferenceType ReferenceType { get { return this._attributeData.ReferenceType; } }
29,662,308✔
17

18
                public int AssignedCode
19
                {
20
                        get
21
                        {
18✔
22
                                if (this._assignedCode.HasValue)
18!
23
                                        return this._assignedCode.Value;
18✔
24

25
                                if (this.DxfCodes.Length == 1)
×
26
                                        return this.DxfCodes.First();
×
27
                                else
28
                                        return (int)DxfCode.Invalid;
×
29
                        }
18✔
30
                }
31

32
                public int[] DxfCodes { get { return this._attributeData.ValueCodes.Select(c => (int)c).ToArray(); } }
933,718✔
33

34
                protected int? _assignedCode;
35

36
                protected PropertyInfo _property;
37

38
                protected T _attributeData;
39

40
                protected DxfPropertyBase(PropertyInfo property)
529,613✔
41
                {
529,613✔
42
                        this._attributeData = property.GetCustomAttribute<T>();
529,613✔
43

44
                        if (this._attributeData == null)
529,612✔
45
                                throw new ArgumentException($"The property does not implement the {nameof(DxfCodeValueAttribute)}", nameof(property));
1✔
46

47
                        this._property = property;
529,611✔
48
                }
529,611✔
49

50
                /// <summary>
51
                /// Set the value for the property using the AssignedCode
52
                /// </summary>
53
                /// <typeparam name="TCadObject"></typeparam>
54
                /// <param name="obj"></param>
55
                /// <param name="value"></param>
56
                /// <exception cref="InvalidOperationException"></exception>
57
                public void SetValue<TCadObject>(TCadObject obj, object value)
58
                        where TCadObject : CadObject
59
                {
9✔
60
                        if (this.AssignedCode == (int)DxfCode.Invalid)
9!
61
                                throw new InvalidOperationException("This property has multiple dxf values assigned or doesn't have a default value assigned");
×
62

63
                        this.SetValue(this.AssignedCode, obj, value);
9✔
64
                }
9✔
65

66
                /// <summary>
67
                /// Sets the value of a specified property on a CAD object, converting the value as needed based on the property's
68
                /// type.
69
                /// </summary>
70
                /// <remarks>This method supports setting values for various property types, including vectors (<see
71
                /// cref="XY"/> and <see cref="XYZ"/>), colors (<see cref="Color"/>), margins (<see cref="PaperMargin"/>),
72
                /// transparency (<see cref="Transparency"/>), and other primitive or enum types. The behavior of the method depends
73
                /// on the property's type and the provided <paramref name="code"/>.</remarks>
74
                /// <typeparam name="TCadObject">The type of the CAD object on which the property value is being set. Must derive from <see cref="CadObject"/>.</typeparam>
75
                /// <param name="code">A code that determines how the value should be interpreted or applied. The interpretation of this code depends on
76
                /// the property's type.</param>
77
                /// <param name="obj">The CAD object whose property value is being set. Cannot be <see langword="null"/>.</param>
78
                /// <param name="value">The value to set for the property. The value will be converted to the appropriate type based on the property's
79
                /// type.</param>
80
                public void SetValue<TCadObject>(int code, TCadObject obj, object value)
81
                        where TCadObject : CadObject
82
                {
9✔
83
                        if (this._property.PropertyType.IsEquivalentTo(typeof(XY)))
9✔
84
                        {
2✔
85
                                XY vector = (XY)this._property.GetValue(obj);
2✔
86

87
                                int index = (code / 10) % 10 - 1;
2✔
88
                                vector[index] = Convert.ToDouble(value);
2✔
89

90
                                this._property.SetValue(obj, vector);
2✔
91
                        }
2✔
92
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(XYZ)))
7✔
93
                        {
3✔
94
                                XYZ vector = (XYZ)this._property.GetValue(obj);
3✔
95

96
                                int index = (code / 10) % 10 - 1;
3✔
97
                                vector[index] = Convert.ToDouble(value);
3✔
98

99
                                this._property.SetValue(obj, vector);
3✔
100
                        }
3✔
101
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(Color)))
4!
UNCOV
102
                        {
×
UNCOV
103
                                switch (code)
×
104
                                {
105
                                        case 62:
UNCOV
106
                                                this._property.SetValue(obj, new Color((short)value));
×
UNCOV
107
                                                break;
×
108
                                        case 420:
UNCOV
109
                                                byte[] b = LittleEndianConverter.Instance.GetBytes((int)value);
×
110
                                                // true color
UNCOV
111
                                                this._property.SetValue(obj, new Color(b[2], b[1], b[0]));
×
UNCOV
112
                                                break;
×
113
                                }
UNCOV
114
                        }
×
115
                        else if (_property.PropertyType.IsEquivalentTo(typeof(PaperMargin)))
4!
UNCOV
116
                        {
×
UNCOV
117
                                PaperMargin margin = (PaperMargin)_property.GetValue(obj);
×
118

UNCOV
119
                                switch (code)
×
120
                                {
121
                                        //40        Size, in millimeters, of unprintable margin on left side of paper
122
                                        case 40:
UNCOV
123
                                                margin = new PaperMargin((double)value, margin.Bottom, margin.Right, margin.Top);
×
UNCOV
124
                                                break;
×
125
                                        //41        Size, in millimeters, of unprintable margin on bottom of paper
126
                                        case 41:
UNCOV
127
                                                margin = new PaperMargin(margin.Left, (double)value, margin.Right, margin.Top);
×
UNCOV
128
                                                break;
×
129
                                        //42        Size, in millimeters, of unprintable margin on right side of paper
130
                                        case 42:
UNCOV
131
                                                margin = new PaperMargin(margin.Left, margin.Bottom, (double)value, margin.Top);
×
UNCOV
132
                                                break;
×
133
                                        //43        Size, in millimeters, of unprintable margin on top of paper
134
                                        case 43:
UNCOV
135
                                                margin = new PaperMargin(margin.Left, margin.Bottom, margin.Right, (double)value);
×
UNCOV
136
                                                break;
×
137
                                }
138

UNCOV
139
                                this._property.SetValue(obj, margin);
×
UNCOV
140
                        }
×
141
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(Transparency)))
4!
UNCOV
142
                        {
×
UNCOV
143
                                this._property.SetValue(obj, Transparency.FromAlphaValue((int)value));
×
UNCOV
144
                        }
×
145
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(bool)))
4!
UNCOV
146
                        {
×
UNCOV
147
                                this._property.SetValue(obj, Convert.ToBoolean(value));
×
UNCOV
148
                        }
×
149
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(char)))
4!
UNCOV
150
                        {
×
UNCOV
151
                                this._property.SetValue(obj, Convert.ToChar(value));
×
UNCOV
152
                        }
×
153
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(byte)))
4!
UNCOV
154
                        {
×
UNCOV
155
                                this._property.SetValue(obj, Convert.ToByte(value));
×
UNCOV
156
                        }
×
157
                        else if (this._property.PropertyType.IsEnum)
4!
158
                        {
4✔
159
                                this._property.SetValue(obj, Enum.ToObject(this._property.PropertyType, value));
4✔
160
                        }
4✔
UNCOV
161
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(ushort)))
×
162
                        {
×
163
                                this._property.SetValue(obj, Convert.ToUInt16(value));
×
164
                        }
×
165
                        else
UNCOV
166
                        {
×
UNCOV
167
                                this._property.SetValue(obj, value);
×
UNCOV
168
                        }
×
169
                }
9✔
170

171
                public object GetValue<TCadObject>(int code, TCadObject obj)
172
                {
13,065✔
173
                        switch (this._attributeData.ReferenceType)
13,065!
174
                        {
175
                                case DxfReferenceType.Unprocess:
176
                                        return this._property.GetValue(obj);
×
177
                                case DxfReferenceType.Handle:
178
                                        return this.getHandledValue(obj);
×
179
                                case DxfReferenceType.Name:
180
                                        return this.getNamedValue(obj);
×
181
                                case DxfReferenceType.Count:
182
                                        return this.getCounterValue(obj);
×
183
                                case DxfReferenceType.None:
184
                                default:
185
                                        return getRawValue(code, obj);
13,065✔
186
                        }
187
                }
13,065✔
188

189
                internal void SetValue(int code, object obj, object value)
190
                {
2,296,431✔
191
                        if (this._property.PropertyType.IsEquivalentTo(typeof(XY)))
2,296,431✔
192
                        {
19,954✔
193
                                XY vector = (XY)this._property.GetValue(obj);
19,954✔
194

195
                                int index = (code / 10) % 10 - 1;
19,954✔
196
                                vector[index] = Convert.ToDouble(value);
19,954✔
197

198
                                this._property.SetValue(obj, vector);
19,954✔
199
                        }
19,954✔
200
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(XYZ)))
2,276,477✔
201
                        {
1,088,970✔
202
                                XYZ vector = (XYZ)this._property.GetValue(obj);
1,088,970✔
203

204
                                int index = (code / 10) % 10 - 1;
1,088,970✔
205
                                vector[index] = Convert.ToDouble(value);
1,088,970✔
206

207
                                this._property.SetValue(obj, vector);
1,088,970✔
208
                        }
1,088,970✔
209
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(Color)))
1,187,507✔
210
                        {
159,248✔
211
                                switch (code)
159,248✔
212
                                {
213
                                        case 62:
214
                                                this._property.SetValue(obj, new Color((short)value));
120,750✔
215
                                                break;
120,750✔
216
                                        case 420:
217
                                                byte[] b = LittleEndianConverter.Instance.GetBytes((int)value);
7,910✔
218
                                                // true color
219
                                                this._property.SetValue(obj, new Color(b[2], b[1], b[0]));
7,910✔
220
                                                break;
7,910✔
221
                                }
222
                        }
159,248✔
223
                        else if (_property.PropertyType.IsEquivalentTo(typeof(PaperMargin)))
1,028,259✔
224
                        {
3,768✔
225
                                PaperMargin margin = (PaperMargin)_property.GetValue(obj);
3,768✔
226

227
                                switch (code)
3,768✔
228
                                {
229
                                        //40        Size, in millimeters, of unprintable margin on left side of paper
230
                                        case 40:
231
                                                margin = new PaperMargin((double)value, margin.Bottom, margin.Right, margin.Top);
942✔
232
                                                break;
942✔
233
                                        //41        Size, in millimeters, of unprintable margin on bottom of paper
234
                                        case 41:
235
                                                margin = new PaperMargin(margin.Left, (double)value, margin.Right, margin.Top);
942✔
236
                                                break;
942✔
237
                                        //42        Size, in millimeters, of unprintable margin on right side of paper
238
                                        case 42:
239
                                                margin = new PaperMargin(margin.Left, margin.Bottom, (double)value, margin.Top);
942✔
240
                                                break;
942✔
241
                                        //43        Size, in millimeters, of unprintable margin on top of paper
242
                                        case 43:
243
                                                margin = new PaperMargin(margin.Left, margin.Bottom, margin.Right, (double)value);
942✔
244
                                                break;
942✔
245
                                }
246

247
                                this._property.SetValue(obj, margin);
3,768✔
248
                        }
3,768✔
249
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(Transparency)))
1,024,491✔
250
                        {
29,080✔
251
                                this._property.SetValue(obj, Transparency.FromAlphaValue((int)value));
29,080✔
252
                        }
29,080✔
253
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(bool)))
995,411✔
254
                        {
124,498✔
255
                                this._property.SetValue(obj, Convert.ToBoolean(value));
124,498✔
256
                        }
124,498✔
257
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(char)))
870,913✔
258
                        {
2,202✔
259
                                this._property.SetValue(obj, Convert.ToChar(value));
2,202✔
260
                        }
2,202✔
261
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(byte)))
868,711✔
262
                        {
5,690✔
263
                                this._property.SetValue(obj, Convert.ToByte(value));
5,690✔
264
                        }
5,690✔
265
                        else if (this._property.PropertyType.IsEnum)
863,021✔
266
                        {
264,471✔
267
                                this._property.SetValue(obj, Enum.ToObject(this._property.PropertyType, value));
264,471✔
268
                        }
264,471✔
269
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(ushort)))
598,550!
NEW
270
                        {
×
NEW
271
                                this._property.SetValue(obj, Convert.ToUInt16(value));
×
NEW
272
                        }
×
273
                        else
274
                        {
598,550✔
275
                                this._property.SetValue(obj, value);
598,550✔
276
                        }
598,550✔
277
                }
2,296,431✔
278

279
                private ulong? getHandledValue<TCadObject>(TCadObject obj)
280
                {
×
281
                        if (!this._property.PropertyType.HasInterface<IHandledCadObject>())
×
282
                                throw new ArgumentException($"Property {this._property.Name} for type : {obj.GetType().FullName} does not implement IHandledCadObject");
×
283

284
                        IHandledCadObject handled = (IHandledCadObject)this._property.GetValue(obj);
×
285

286
                        return handled?.Handle;
×
287
                }
×
288

289
                private string getNamedValue<TCadObject>(TCadObject obj)
290
                {
×
291
                        if (!this._property.PropertyType.HasInterface<INamedCadObject>())
×
292
                                throw new ArgumentException($"Property {this._property.Name} for type : {obj.GetType().FullName} does not implement INamedCadObject");
×
293

294
                        INamedCadObject handled = (INamedCadObject)this._property.GetValue(obj);
×
295

296
                        return handled?.Name;
×
297
                }
×
298

299
                private int getCounterValue<TCadObject>(TCadObject obj)
300
                {
×
301
                        if (!this._property.PropertyType.HasInterface<IEnumerable>())
×
302
                                throw new ArgumentException();
×
303

304
                        IEnumerable collection = (IEnumerable)this._property.GetValue(obj);
×
305
                        if (collection == null)
×
306
                                return 0;
×
307

308
                        int counter = 0;
×
309
                        foreach (var item in collection)
×
310
                        {
×
311
                                counter++;
×
312
                        }
×
313

314
                        return counter;
×
315
                }
×
316

317
                private object getRawValue<TCadObject>(int code, TCadObject obj)
318
                {
13,065✔
319
                        GroupCodeValueType groupCode = GroupCodeValue.TransformValue(code);
13,065✔
320

321
                        switch (groupCode)
13,065!
322
                        {
323
                                case GroupCodeValueType.Handle:
324
                                case GroupCodeValueType.ObjectId:
325
                                case GroupCodeValueType.ExtendedDataHandle:
326
                                        return this.getHandledValue<TCadObject>(obj);
×
327
                        }
328

329
                        if (this._property.PropertyType.HasInterface<IVector>())
13,065✔
330
                        {
1,005✔
331
                                IVector vector = (IVector)this._property.GetValue(obj);
1,005✔
332

333
                                int index = (code / 10) % 10 - 1;
1,005✔
334
                                return vector[index];
1,005✔
335
                        }
336
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(DateTime)))
12,060✔
337
                        {
1,340✔
338
                                return CadUtils.ToJulianCalendar((DateTime)this._property.GetValue(obj));
1,340✔
339
                        }
340
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(TimeSpan)))
10,720✔
341
                        {
335✔
342
                                return ((TimeSpan)this._property.GetValue(obj)).TotalDays;
335✔
343
                        }
344
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(Color)))
10,385!
345
                        {
×
346
                                //TODO: Implement color getter
347
                                Color color = (Color)this._property.GetValue(obj);
×
348

349
                                switch (code)
×
350
                                {
351
                                        case 62:
352
                                        case 70:
353
                                                return color.Index;
×
354
                                        case 420:
355
                                                // true color
356
                                                return color.TrueColor;
×
357
                                        case 430:
358
                                                // dictionary color
359
                                                break;
×
360
                                }
361

362
                                return null;
×
363
                        }
364
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(PaperMargin)))
10,385!
365
                        {
×
366
                                switch (code)
×
367
                                {
368
                                        case 40:
369
                                                return ((PaperMargin)this._property.GetValue(obj)).Left;
×
370
                                        case 41:
371
                                                return ((PaperMargin)this._property.GetValue(obj)).Bottom;
×
372
                                        case 42:
373
                                                return ((PaperMargin)this._property.GetValue(obj)).Right;
×
374
                                        case 43:
375
                                                return ((PaperMargin)this._property.GetValue(obj)).Top;
×
376
                                        default:
377
                                                throw new Exception();
×
378
                                }
379
                        }
380
                        else if (this._property.PropertyType.IsEquivalentTo(typeof(Transparency)))
10,385!
381
                        {
×
382
                                //TODO: Implement transparency getter
383
                                //return this._property.GetValue(obj);
384
                                return null;
×
385
                        }
386
                        else
387
                        {
10,385✔
388
                                return this._property.GetValue(obj);
10,385✔
389
                        }
390
                }
13,065✔
391
        }
392
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc