Author Topic: Custom Class Types  (Read 2631 times)

0 Members and 1 Guest are viewing this topic.

BlackBox

  • King Gator
  • Posts: 3770
Custom Class Types
« on: September 23, 2012, 11:40:18 AM »
I seem to be having trouble with what I thought was a basic skill with .NET development, in implementing custom Class types, Employee, and Company (which inherits from CollectionBase).

In the example below, I am attempting to use IExtensionApplication.Initialize() to perform the simple task of printing each Employee.Name in a Company() (a List<Employee>) to the command line.

When I NETLOAD the assembly, I can step through the code, the first Employee(person) is created, but when I reach company.Add(employee); I'm returned to my debug session of AutoCAD with nothing at the command line.

I do not understand why company.Add(employee) is failing... Any suggestions?

Code - C#: [Select]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5.  
  6. using acApp = Autodesk.AutoCAD.ApplicationServices.Application;
  7.  
  8. using System;
  9. using System.Collections;
  10. using System.Collections.Generic;
  11.  
  12. [assembly: ExtensionApplication(typeof(FOO.TEST))]
  13.  
  14. namespace FOO
  15. {
  16.     class TEST : IExtensionApplication
  17.     {
  18.         void IExtensionApplication.Initialize()
  19.         {
  20.             Editor ed = acApp.DocumentManager.MdiActiveDocument.Editor;
  21.             Company company = new Company();
  22.  
  23.             foreach (Employee emp in company)
  24.             {
  25.                 ed.WriteMessage("\n** Employee: ({0}) ** \n", emp.Name);
  26.             }
  27.         }
  28.  
  29.         void IExtensionApplication.Terminate()
  30.         {
  31.         }
  32.     }
  33.  
  34.     class Employee
  35.     {
  36.         // fields
  37.         private string empName;
  38.         private string empOffice;
  39.  
  40.         // properties
  41.         public string Name
  42.         {
  43.             get { return empName; }
  44.             set { empName = value; }
  45.         }
  46.  
  47.         public string Office
  48.         {
  49.             get { return empOffice; }
  50.             set { empOffice = value; }
  51.         }
  52.  
  53.         // constructors
  54.         public Employee() { }
  55.  
  56.         public Employee(string name)
  57.         {
  58.             empName = name;
  59.         }
  60.     }
  61.  
  62.     class Company : CollectionBase
  63.     {
  64.         private List<Employee> company;
  65.  
  66.         public Company()
  67.         {
  68.             string[] people = { "employee1", "employee2", "employee3" };
  69.  
  70.             foreach (string person in people)
  71.             {
  72.                 Employee employee = new Employee(person);
  73.                 company.Add(employee); //<-- Seems to break here
  74.             }
  75.         }
  76.     }
  77. }
  78.  

TIA
"How we think determines what we do, and what we do determines what we get."

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Custom Class Types
« Reply #1 on: September 23, 2012, 01:04:42 PM »
Hi,

An exception occurs when you try to add an item to the 'company' List because it have been declared but it have not been instanciated (it is null).
Anyway, even after having instanciated company (with company = new List<Employee>();) you fill a private list, not the new created instance of Company which keeps empty.

Some suggestions:
First, while you're trying to do something which is not related to AutoCAD, you'd rather use a Console Application, so that debugging will be faster.
By my side, I won't make the Company class inherit from CollectionBase which is not strongly typed, an easier way would be using a List<Employee> as base class (you'd can override the List<T> class methods if needed).

Code - C#: [Select]
  1.     class Program
  2.     {
  3.         static void Main()
  4.         {
  5.             Company company = new Company();
  6.             foreach (Employee emp in company)
  7.             {
  8.                 Console.WriteLine(emp.Name);
  9.             }
  10.  
  11.             Console.ReadLine();
  12.         }
  13.     }
  14.  
  15.     class Employee
  16.     {
  17.         // properties
  18.         public string Name { get; set; }
  19.  
  20.         public string Office { get; set; }
  21.  
  22.         // constructors
  23.         public Employee() { }
  24.  
  25.         public Employee(string name)
  26.         {
  27.             Name = name;
  28.         }
  29.     }
  30.  
  31.     class Company : List<Employee>
  32.     {
  33.         public Company()
  34.         {
  35.             string[] people = { "employee1", "employee2", "employee3" };
  36.             foreach (string person in people)
  37.             {
  38.                 Employee employee = new Employee(person);
  39.                 this.Add(employee);
  40.             }
  41.         }
  42.     }
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Custom Class Types
« Reply #2 on: September 23, 2012, 02:16:13 PM »
Another way much more like your code (with a private List<Employee> encapsulation), would be to implement a strongly typed interface, almost IEnumerable<Employee> which is necessary to call 'foreach' on a Company class instance.
You can implement others interfaces which inherit from IEnumerable<T> as ICollection<T>, IList<T> if you want your Company class to implement these interfaces members.

Code - C#: [Select]
  1.     class Company : IEnumerable<Employee>
  2.     {
  3.         private List<Employee> company;
  4.  
  5.         public Company()
  6.         {
  7.             string[] people = { "employee1", "employee2", "employee3" };
  8.             company = new List<Employee>();
  9.             foreach (string person in people)
  10.             {
  11.                 Employee employee = new Employee(person);
  12.                 company.Add(employee);
  13.             }
  14.         }
  15.  
  16.         #region IEnumerable<Employee> Membres
  17.  
  18.         public IEnumerator<Employee> GetEnumerator()
  19.         {
  20.             foreach (Employee emp in company)
  21.             {
  22.                 yield return emp;
  23.             }
  24.         }
  25.  
  26.         #endregion
  27.  
  28.         #region IEnumerable Membres
  29.  
  30.         IEnumerator IEnumerable.GetEnumerator()
  31.         {
  32.             return this.GetEnumerator();
  33.         }
  34.  
  35.         #endregion
  36.     }
Speaking English as a French Frog

TheMaster

  • Guest
Re: Custom Class Types
« Reply #3 on: September 23, 2012, 06:04:50 PM »
Before I finish reading this thread, let me just say that experimenting with generic programming tasks that have little to do with or no dependence on AutoCAD is like trying to learn how to fly in a B52 bomber.

There are quite a few cases where AutoCAD will trap an exception raised by a plug in, and simply suppress it, without giving so much as a hint that the exception occurred, or why (most notably, IExtensionApplication.Initialize() or any code called from that method, which is what got you here).

There are also cases where AutoCAD does not bother to catch any exceptions raised by a plug in, and simply crashes (most commonly in cases where the managed code is being called from native code, like event handlers and the virtual methods of Overrule-based types).

So, may I first ask why you are using the B52 bomber when you should be in a piper cub (e.g., a simple console application, or even Windows Forms application if that makes you more comfortable) ?

By doing this kind of stuff in AutoCAD you are making things much harder than they need to be, unless you are doing things that have some dependence on AutoCAD, rather than generic code that involves theoretical objects like 'Company' and 'Employee'.

I seem to be having trouble with what I thought was a basic skill with .NET development, in implementing custom Class types, Employee, and Company (which inherits from CollectionBase).

In the example below, I am attempting to use IExtensionApplication.Initialize() to perform the simple task of printing each Employee.Name in a Company() (a List<Employee>) to the command line.

When I NETLOAD the assembly, I can step through the code, the first Employee(person) is created, but when I reach company.Add(employee); I'm returned to my debug session of AutoCAD with nothing at the command line.

I do not understand why company.Add(employee) is failing... Any suggestions?

Code - C#: [Select]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5.  
  6. using acApp = Autodesk.AutoCAD.ApplicationServices.Application;
  7.  
  8. using System;
  9. using System.Collections;
  10. using System.Collections.Generic;
  11.  
  12. [assembly: ExtensionApplication(typeof(FOO.TEST))]
  13.  
  14. namespace FOO
  15. {
  16.     class TEST : IExtensionApplication
  17.     {
  18.         void IExtensionApplication.Initialize()
  19.         {
  20.             Editor ed = acApp.DocumentManager.MdiActiveDocument.Editor;
  21.             Company company = new Company();
  22.  
  23.             foreach (Employee emp in company)
  24.             {
  25.                 ed.WriteMessage("\n** Employee: ({0}) ** \n", emp.Name);
  26.             }
  27.         }
  28.  
  29.         void IExtensionApplication.Terminate()
  30.         {
  31.         }
  32.     }
  33.  
  34.     class Employee
  35.     {
  36.         // fields
  37.         private string empName;
  38.         private string empOffice;
  39.  
  40.         // properties
  41.         public string Name
  42.         {
  43.             get { return empName; }
  44.             set { empName = value; }
  45.         }
  46.  
  47.         public string Office
  48.         {
  49.             get { return empOffice; }
  50.             set { empOffice = value; }
  51.         }
  52.  
  53.         // constructors
  54.         public Employee() { }
  55.  
  56.         public Employee(string name)
  57.         {
  58.             empName = name;
  59.         }
  60.     }
  61.  
  62.     class Company : CollectionBase
  63.     {
  64.         private List<Employee> company;
  65.  
  66.         public Company()
  67.         {
  68.             string[] people = { "employee1", "employee2", "employee3" };
  69.  
  70.             foreach (string person in people)
  71.             {
  72.                 Employee employee = new Employee(person);
  73.                 company.Add(employee); //<-- Seems to break here
  74.             }
  75.         }
  76.     }
  77. }
  78.  

TIA
« Last Edit: September 23, 2012, 06:28:30 PM by TT »

TheMaster

  • Guest
Re: Custom Class Types
« Reply #4 on: September 23, 2012, 06:41:51 PM »
I seem to be having trouble with what I thought was a basic skill with .NET development, in implementing custom Class types, Employee, and Company (which inherits from CollectionBase).

In the example below, I am attempting to use IExtensionApplication.Initialize() to perform the simple task of printing each Employee.Name in a Company() (a List<Employee>) to the command line.

When I NETLOAD the assembly, I can step through the code, the first Employee(person) is created, but when I reach company.Add(employee); I'm returned to my debug session of AutoCAD with nothing at the command line.

I do not understand why company.Add(employee) is failing... Any suggestions?


Gile already covered most of the bases, so my only comment is that when we design classes or frameworks, we need to do it in a way that keeps our options open for things that may be needed in the future, including things we haven't thought of yet, and avoid doing things in ways that impose restrictions on the design and any future requirements.

For example, using your 'Company' and 'Employee', a Company is logically comprised of many things besides employees, like for example, one or more physical locations, products or services, and countless other things that might be represented as collections. So for example, your Company object may need to provide access to a collection of business locations, a collection of company directors, a collection of outside consultants, a collection of departments, etc...

So, the first thing I'd avoid doing, is making your Company object an IEnumerable of anything, because there will most-likely be many collections of varying types of objects that would need to be accessible through an instance of a Company object.

For that reason, it'd be more appropriate to implement properties that provide access to various collections, which can be custom collection types, or built-in collection types, as needed. So for example, a Company object may have an Employees property whose type is ICollection<Employee>, and a Departments property whose type is an ICollection<Department>, and so on....

BlackBox

  • King Gator
  • Posts: 3770
Re: Custom Class Types
« Reply #5 on: September 23, 2012, 08:45:11 PM »
First, please forgive the ambiguity of 'Employee' and 'Company'... That was simply the arbitrary result of some reading through an example from a chapter in the .NET book I am reading, paired with a task I am attempting to perform in AutoCAD.

Perhaps instead of my original post, I should have verbalized the task at hand for input and guidance from others, but I generally like to make an attempt to the best of my abilities first.



This is simply the next step (task) in an application that ties into my Event plug-in from the other thread.

Ultimately, it is my intention to employ my plug-in to invoke a Method each time the DocumentCreated Event fires. This Method is intended to iterate a list of strings, using FindFile() and System.IO to perform a few internal tasks to our CAD Standards.

I can already iterate this small list of strings using standard means (aka the piper cub, a hard-coded list wrapped in a foreach block), and am attempting to build-in some flexibility for future enhancement(s), thus my seeking a custom Class, both for the string objects, and for the collection of.

My thought (albeit potentially misguided), was to define the singular object class which would allow me the flexibility to add additional Properties, etc. down the road as currently I need only Name and Path Properties for each instance of this object. Then, for the Method being invoked via DocumentCreated Event, simply create a new instance of the Collection Class, which already includes an iterable List, etc. of the newly created objects... Then to simply search the Database for Findfile(object.Name ....).

myClass.Collection would very much be workable, I just wasn't sure how to accomplish that, and was hoping the structure I presented in the OP was simpler, without being simplistic.

You're correct, I am not capable of flying a B-52 at present... Especially given my background for jumping out of C-130, and C-141 with about 150 of my fellow Soldiers. LoL
"How we think determines what we do, and what we do determines what we get."

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: Custom Class Types
« Reply #6 on: September 23, 2012, 08:58:03 PM »
Ha!  my first thought , piper cubs take like a freaking hour to get to a good jump altitude , give me the ol 1943 beechcraft please   :lol:

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Custom Class Types
« Reply #7 on: September 23, 2012, 09:51:35 PM »

:)
Ya gotta love discussion digression at theSwamp.

 :-D
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

BlackBox

  • King Gator
  • Posts: 3770
Re: Custom Class Types
« Reply #8 on: September 24, 2012, 12:16:49 AM »
Always happy to contribute :-D
"How we think determines what we do, and what we do determines what we get."