ObjectFactory with different types of BOs

ObjectFactory with different types of BOs

Old forum URL: forums.lhotka.net/forums/t/11021.aspx


mspaourh posted on Tuesday, December 27, 2011

Hi everyone,

Is it possible to use a single ObjectFactory class that determines the type of BO to operate on at run-time?

There is a custom base class (e.g subclass of ReadOnlyBase<T>) that has the ObjectFactoryAttribute applied on it and all its subclasses should use the same ObjectFactory, unless otherwise specified.

There seems to be no way of communicating the actual business object type from the FactoryDataPortal to the ObjectFactory instance.

Using CSLA 3.8.4

 

Thanks in advance,

Mario

JonnyBee replied on Tuesday, December 27, 2011

Hmmmm,

You could create your own ObjectFactoryLoader  - responsible for creating an instance of the ObjectFactory.

Basically the name is just a string (and using the default ObjectFactoryLoader this should be a fully qualified class name) and optionally  specify other names for the Create/Update/Delete/Fetch methods.

And if you create your own ObjectFactoryLoader you can decide yourself what the name value should contain. Meaning that you could specify the ObjectFactory attribute with a fully qualified name and actual type - andimplement your own convention to initialize the factory class with actual type name,  tho' that would require an ObjectFactoryAttribute on each class.

You should be able to use a generic constraint on the ObjectFactory class - but this would also require the ObjectFactory attribute on each class. It would however allow you to have an object factory that could create multiple types.

  [ObjectFactory(typeof(MyRootFactory<Root>))]
  public class Root : BusinessBase<Root>

and
  public class MyRootFactory<T> : Csla.Server.ObjectFactory
  {
 
    public T Create()
    {
      T o = (T)MethodCaller.CreateInstance(typeof(T));
 
      return o;
    }
}
this will work with the default ObjectFactoryLoader.

Besides that - I do not know of any other method or provision for sending the actual object type to the ObjectFactory! Hmm

 

mspaourh replied on Tuesday, December 27, 2011

JonnyBee,

thanks for your answer.

I am trying to drop the requirement of applying the ObjectFactoryAttribute to each subclass.

The intention is to provide a "default" behavior for all subclasses of the custom base class by applying the attribute to the custom

base class. The behavior can be replaced by explicitly applying the attribute to some subclass.

I am aware of the ObjectFactoryLoader class and the IObjectFactoryLoader interface and was intending

to use them in this concept. The custom ObjectFactoryLoader could use

public virtual Type MakeGenericType(
    Type[] typeArguments
)

on the System.Type instance "described" (by interpreting the string) in the ObjectFactoryAttribute to make a closed constructed type,
but the actual BO type (Root in your example) required for typeArguments is missing from the whole "context".

JonnyBee replied on Tuesday, December 27, 2011

Hi,

Yes, you are correct and IMO it is not intended to work the way you want to use it.

An ObjectFactory must have knowledge of how to create/fetch/update/delete the data and maintain state in the BO. And for an object structure with miltiple levels it must also have knowledge of all the child object factories.

The ObjectFactoryAttribute is only intended to be used on "root" objects - ie CSLA DataPortal will only use the ObjectFacotryAttribute for the "root" object. .

 

mspaourh replied on Wednesday, December 28, 2011

Hi,

The use of factories in general is required due to plugging of different DALs. An ObjectFactoryLoader takes care of that.

 

Let me explain what is the goal here. There dozens of database tables (and hence BOs) that have identical structure, e.g.

ID INT NOT NULL PRIMARY KEY,

CODE NVARCHAR(5),

DESCR NVARCHAR(50)

When their data is loaded in an list (editable or read-write) its done with an SQL statement like

SELECT ID, CODE, DESCR FROM <<tableName>>

and when they are loaded as root objects its done with

SELECT ID, CODE, DESCR FROM <<tableName>> WHERE ID=@ID
. Same pattern with the insert, update, delete statements.

tableName can be derived from the business object type name (using the appropriate convention, or a user-defined attribute in the worst case).

All of the relevant business object classes are derived from the appropriate custom base class.

The "generic" factory is a reasonable choice because is a time and effort saver.

Currently the only limitation for this implementation is the requirement to place an ObjectFactory (or a custom subclass of it!) to every business object class!

JonnyBee replied on Wednesday, December 28, 2011

For now - my recommendation would be to create a ObjectFactory derived base class (ex NameValueListFactory)  to implement the "generic" object factory and create a new (nearly empty) ObjectFactory class to keep 1:1 mapping between object type and table.

The actual ObjectFactory would inherit from the NameValueListFactory and just set the table name to use.

 

 

mspaourh replied on Thursday, December 29, 2011

Thanks jonny.

 

Although its not what I actually planned, i'll just stick with that.

 

Happy 2012 to everyone!

 

Mario

Copyright (c) Marimer LLC