ObjectFactory Send Feedback on this Topic

Getting Started

When a system has been modelled using the Constructor Model Objecteer, and the Run Time Model has been created (see documentation), you can start programming against Constructor objects to produce a Win32 application or Web application.

All objects that are requested from the runtime model are dynamic, that is they do not require a concrete class. They reside in a dynamic module which in turn resides in a dynamic assembly.

Exposing a class or property produces an abstract class in which you can write specific code or intercept property assignment. The programmer uses the ObjectFactory to create, query and retrieve objects.

All classes that you define, when implemented, derive from a BaseClass, named, ConstructorClass. The ConstructorClass has a rich set of methods and properties which are at the disposal of the Programmer. The ObjectSet class is the BaseClass for all the Constructor typed collections.

Concepts

This section describes the rationale behind Constructor objects, to aid your understanding of the ObjectFactory model.

Declaring Constructor Objects

Since the runtime model contains all of the defined programmable interfaces, all Constructor objects supports Intellisense. The creation of objects via the ObjectFactory only supports those classes which have been defined in the model. Therefore all Constructor objects have to be declared as a certain type. These objects are programmed against interfaces, the interfaces for each of classes defined in the model are contained within the Run Time Model Assembly; using the pubs tutorial you would declare your objects as Iemployee, IemployeeSet , Iauthor, Ijobs etc.

QueryObject

Queries to the database to populate objects are performed through this object (except for the ObjectFactory.GetObjects method). A QueryObject is created from the type you need to query. For example, if you are performing a query against the Authors table, you would create a QueryObject of type IAuthorQuery. Therefore the QueryObject of type IAuthorQuery has the same structure as an Author object.

By setting the properties of the IAuthorQuery object (for example), these will be used to build the relevant SQL statements. The QueryObject supports Stored Procedures and the properties of the QueryObject can be used as the parameters for the stored procedure.

Once populated, calling the _GetObjects method will call the underlying data store with the appropriate SQL Statements.

ObjectSet:- the Constructors typed

An ObjectSet is a collection of objects with the same type. For example a collection of Employee objects will be declared as IEmployeeSet. Locating an object in an ObjectSet will return an object of a specific type. All Constructor object collections are inherited from the ObjectSet class.

With any Objectset the Objects within the collection can be accessed directly by Index or by Key. When Objects are retrieved from the database they are added to the internal collection keyed on the Data table key columns. If the key is composite then the keys will be concatenated. When a new object is added to the collection a surrogate key is generated if one has not been supplied by the programmer.

ObjectSetView

A major function of the ObjectSetView is to allow object binding on both Windows Forms and Web Forms. An ObjectSetView can view data in different ways without affecting the underlying data. As its name implies an ObjectSetView is based on the underlying ObjectSet.

ObjectView

An ObjectView is a single object view contained in the ObjectSetView Collection and maps to the Objects contained in the ObjectSet.

Dynamic Types

With Constructor you do not have to create a class in your project to create and use an object, if the object is only used for data access. The ObjectFactory is aware of all classes (types) via a generated Run Time Model. When The Object Factory is requested to create an object of a certain type, it will determine if the request is valid from this run time model. If it is valid and this is the first request of this type, it will then create this type in the dynamic assembly.

In your project you may have requested Constructor to generate one or more classes by exposing them. You can write code to add extra functionality to exposed classes.

All Constructor objects can only be created by using CreateObject method from the ObjectFactory. This is because all types are dynamic. If you had generated a class, the generated class will be abstract and it will be marked as MustInherit (in VB code) or Abstract (in C# code), therefore you cannot use the New keyword to obtain an object from this class; you must use the ObjectFactory to create an object for you.

What happens in memory

When the ObjectFactory has been initialised, it creates a dynamic module in a dynamic assembly in memory. All requests to create an object of a certain type will create the objects type in the dynamic assembly. Therefore an objects type needs only to be created in memory once. All further requests for the same type of object can be retrieved from the dynamic assembly.

The Object network

Constructor classes may have a relationship between them (i.e. an association). This association allows the programmer to use the dot notation to navigate between the objects. For example

Employees(0).jobs.job_desc.

This notation is showing that in the collection of Employee objects, the first element (an employee object) references the Jobs object and the Jobs Object has a property named job_desc.

Binding objects

All Objects that are dispensed via the Object Factory can be bound to datagrids, textboxes, labels and so on. This is because they support the following .NET interfaces:- IListSource, IBindingList, ICustomTypeDescriptor, ITypedList and IEditableObject. Even a QueryObject can be bound. For example, you can get the user to input values from a form and those values would be directly mapped to a QueryObjects properties. The accompanying tutorial shows binding examples.

Base classes

All Objects which are created from the ObjectFactory are inherited from other Constructor base classes. Singleton classes inherit from the ConstructorClass. Collections inherit from the ObjectSet.

This allows the programmer to use a set of standard methods/properties for the created objects. For example if you have modified an Employee object you can call the Update method to commit changes back to the database. To ensure that methods/properties on the ConstructorClass do not conflict with methods/properties defined in the model, they are prefixed with the _ (underscore) character e.g. _Update.

Getting and Manipulating Objects

Creating a New Object

When any Object has been created from the ObjectFactory and the classes have been exposed, you can write code to intercept the newly created objects. Exposed classes may have a method named Constructor (If you have modelled an operation in the Model Objecteer). This method will be called by the ObjectFactory when it has created the Object for you. You can define and pass parameters to the Constructor method for your class. See tutorials.

Obtaining objects from the database is achieved via the Object Factory GetObjects method or the QueryObject methods GetObjects/GetObject. Depending on the type of query you need to perform you would use either the ObjectFactory method or the QueryObject methods. Using the ObjectFactory method will return all Objects for that type from the database (i.e Type employee will return all Employee objects). Using the QueryObject you can submit more complex queries to the database. The QueryObject properties may be populated and these will be used to make up the SQL query. The QueryObject can also cater for Stored Procedures to populate the objects.

Creating a new object is achieved via the Object Factory method CreateObject. Any default values which have been modelled will be assigned to the properties of the newly created Object. All Objects may be modelled with a constructor named Constructor (!) and any arguments you pass to the method CreateObject can be intercepted here.

Once an object has been obtained (existing or new) you can then assign properties and call methods on that object. To commit changes back to the database you would call the Updatemethod either on the Object or on the Objectset. From the context of the parent object, if it references other subordinate objects, by default it will update them back to the database as well. The status of the object will determine what type of call to the database is made. For example, if the object is a new object then calling the update method on that object will in turn create an insert statement (or call the stored procedure for an insert) for the underlying database. If the objects state is modified/deleted then the appropriate update/deleted statement will be created and issued (again a stored procedure could be used here instead).

Sorting Objects

With ObjectSets there is a method named DefaultView. The DefaultView method returns an ObjectSetView which you can invoke the Sort method, with a sort criteria. (A sort criteria uses a filter expression, which is explained below). Once you have defined the sort criteria you can bind the ObjectSetView to a DataGrid and view the Objects sorted. However if your sort criteria is a simple sort i.e. au_fname desc (see filter expressions) you could click on the DataGrid column header to sort descending by that column. By clicking on the same column header again the column will be sorted ascending. This is the default behaviour for all bound ObjectSetViews.

Filtering Objects Client Side

Again like sorting objects which uses an ObjectSetView, you can use the same view for filtering. Once an ObjectSetView is obtained (by calling the DefaultView method on an ObjectSet) you can specify a filter expression (see filter expressions). Once you have defined a filter expression you can bind the ObjectSetView to a DataGrid to view the filtered objects. Note you can combine the Sorting and filtering to the same ObjectSetView.

Filtering Objects Server Side

To obtain objects from the database you would use a QueryObject and invoke methods GetObjects/GetObject. For example if you retrieved an ObjectSet filled with Customer objects and in the model there is a relationship between Customer and Orders, using the dot notation you can navigate to the Orders objects for that Customer. Since the model dictates that there are many Orders for a Customer, the orders will return an ObjectSet (a set of Orders). Therefore the default behaviour (in this example) is to return all Orders for that Customer. This may be acceptable to use this default behaviour, however for large numbers of related objects this behaviour may become unacceptable. To override the default behaviour when retrieving sub ObjectSets from a parent, on every parent object there is a property named <Object>Filter for each referenced ObjectSet. This is a QueryObject and its purpose is to limit (filter) the number of objects returned from a database by specifying a query. See tutorials

Filter Expressions

When sorting and filtering objects on client side the ObjectSetView uses .NET Filter Expressions for the criteria. See .Net documentation on how to use filter expressions.

Inherited Objects

In the model Objecteer you can define a class which is derived from another class (known as a Superclass). In tutorial 11, a ScreenWriter object is inherited from an Author object and all properties and methods defined in the Author object are now available in the ScreenWriter Object. The ObjectFactory relates the Author and ScreenWriter data for you, all you have to do as a programmer, is request the ScreenWriter or an Author object from the ObjectFactory. How the ObjectFactory relates the derived information is like so:- Referring to tutorial 11 example, the Authors database table has been modified to include another column. The new column name is called ConstructorClassName. The purpose of this column is to determine the owner of the data i.e Author or ScreenWriter. The ScreenWriter object has its own database table to hold its data. The ScreenWriters table and the Authors table will have a relationship defined. When a new ScreenWriter object has been saved the type name of the ScreenWriter object will be written to the Authors table ConstructorClassName column. The Authors ID will be written to the ScreenWriters table to form the relation.

Stored Procedures

You can use existing stored procedures with Constructor to update, insert in, delete from and query the database. However:

Assemblies

Earlier in this document, there is mention of dynamic assemblies. With any Constructor project there will be four specific assemblies referenced/used. They are as follows:

Schematic Diagram of Referenced Assemblies

Determining between dynamic and concrete classes

When you have created your application there are two possible scenarios.

How the ObjectFactory determines which classes to use (dynamic or concrete) at runtime is by the referenced assemblies in your project.

When a request comes into ObjectFactory, the ObjectFactory is aware at this point of all referenced assemblies. The ObjectFactory will search the assemblies which have an abstract class of the requested type. If this process finds the requested type the ObjectFactory will create the type derived from the abstract class, then the ObjectFactory will place the newly created type in its dynamic assembly. All code that you have placed in this abstract class will get executed and any breakpoints which have been set the debugger will process.

If no abstract classes for the requested type have been found then the ObjectFactory will create a type based on the interfaces defined in the runtime model, again the newly created type is then placed in the dynamic assembly.

Finally if no requested types have been modelled then an exception is thrown. You can only use the ObjectFactory to create Constructor objects i.e objects which have been modelled in the Model Objecteer.


©2006 i3 Design. All rights reserved.