Component Object Model Tutorial?

Does anyone know a good tutorial (preferably C #) for creating a hierarchical object model for a component for .NET 3.0 or later, does it make full use of generics?

  • works with an unlimited number of contained objects and exposes them
  • Prevent client applications from directly creating instances of contained objects
  • allows client code to use the “tunneling” style, for example.

string columnName = db.Tables["Customers"].Columns["customer_number"].Name;

I found this article Component Recommendations on the Object Model , but since it is for Visual Studio .NET 2003, but I think there are better ways in .NET 3.0.

Thanks.

UPDATE:

If I understand the indexers correctly ...

In the db class, I could use the SortedList container as the table for the table, and for use and the indexer to access the Table instance. Similarly, the Table index will access the Column instance. Thus, the client code may look like this:

string tableName = db["Customers"].Name;

The problem is that the db class provides other collections in addition to Tables ( StoredProcs , DBViews , etc.). Therefore, I think I want to save the collection classes for each, exposing them as properties, rather than using an index. Does this sound right? Should indexes be used for these collection classes?

+4
source share
2 answers
  • Allow client code to use a "tunneling" style, such as

    string columnName = db.Tables["Customers"].Columns["customer_number"].Name;

[...] I want to save collection classes for each, exposing them as properties, and not using an index. Does this sound right?

Yes, it sounds better than indexers, because it helps improve type safety. If you open a regular collection, each of them can have its own element type. Using the indexer, you must select the same collection type for all open collections. To illustrate this fact:

 public DataTable this[string tableName] { ... } // ^^^^^^^^^ // choose one, unspecific type for all exposed collections 

vs.

 public IList<Customer> Customers { get { ... } } public IList<Supplier> Suppliers { get { ... } } // ^^^^^^^^ // the right type for each collection 

So, yes, expose single "typed" collections instead of the "untyped" collection collections.

Side note . You say you want to enable tunneling; some people may tell you that this violates some generally accepted principles of OO, such as the principle of single responsibility (SRP) or separation of concerns (SoC).


  • prevent client applications from directly creating instances of contained objects
 public class Db { public IList<Customer> Customers { get { ... } } ... } 

“Contained objects” can mean two things here:

  • Someone may replace your Customers collection. You simply prevent this by creating a read-only property, i.e. only provide getter.

  • Someone can insert a new Customer into your db.Customers collection. You prevent this by choosing a collection type (read-only) for Customers that does not allow insertion.

For instance:

 private List<Customer> customers = new List<Customer>(); // ^ for class-internal use only public IList<Customer> Customers { get { return this.customers.AsReadOnly(); } } // ^^^^^^^^^^^^^ // expose collection as read-only 

  • work with an unlimited number of contained objects and detect

This again can mean two things:

  • Your db provides an unlimited number of collections. Obviously this will not work if you want each collection to be specially typed. This only works when all your collections are displayed as having the same type (for example, DataTable s or as non-generic ICollection s), and you will need to provide an index. That is, you make your numerous collections accessible through one collection that you open with the indexer.

  • You publish a known and final number of collections (e.g. Customers , Suppliers , etc.). However, each of them can contain as many sub-objects as you want. I assumed this scenario when I wrote the above parts of my answer. The benefits are the best type of security and compilation time checking when tunneling.

Regarding the last point:

 db.Customers["John Smith"].BillingAddress 

vs.

 db.Tables["Customers"].Rows["John Smith"].Columns["BillingAddress"] as Address 

In the first case, the compiler can check the types of properties, such as Customers , BillingAddress , while in the second case, these properties are encoded as strings, and the compiler will not notice if you have typos there. In addition, you must specify the correct data type yourself using cast-types.

+2
source

Read about using indexers in C #. Here is the relevant page .

+1
source

All Articles