Dynamically Create Objects From Class Name

Dynamically Create Objects From Class Name

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


geltendorf posted on Thursday, October 23, 2008

It might sound wierd, but at the moment I don't have any other/better idea how to acomplish this. There is a need to recreate (renew) almost all aubscriptions evry year again based on accounts and subscriptions/transactions from previous year. So naturally, in CSLA i have to clone plenty of objects form previous year to new objects using DataMapper. But, there is a posibility that list of objects to be recreated and persisted is going to change over the time I don't want to to add/remove object name in "Selecet Case" clause list of objects and recompile every time when objects to be cloned are added/removed. The idea is to have a table in database with Object name, Method to call to instatiate object, Criteria to fetch object, parent object id if collection etc. So renewal could be database driven without recompiling the code every time/when list of object is changed over the time. Reflection is not my strong part so anything I've tried in a few days didn't work. I was curious if somebody already did some work with similar requirements and want to share code/snippet/idea with me. So basically, I need to be able to dynamically create object and fetch data based on data from database table as class name, method name to get/fetch data, criteria, parent object id etc. Any help is greatlly appreciated.

rsbaker0 replied on Thursday, October 23, 2008

Yes, you can do this pretty easily.

The key is to construct a System.Type object from the class name. There may be other ways, but I have done this by first building a string that can be resolved into a classname, which is in the format:

Completely.Qualified.Class.Name,Assembly

(For example, "Csla.Core.BusinessBase,Csla")

Then you can use the System.Type functions to retrieve an actual type object. The above class is probably abstract so you can't instantiate it, but any concrete class would work. You can also reflect on static methods in the class (e.g. if you had a class factory method like Create() or GetList()). You can use Activator.CreateInstance() to construct actual object using the System.Type value.

string strClassName =  "Csla.Core.BusinessBase,Csla";

System.Type aType = System.Type.GetType(strClassName, false, true);

geltendorf replied on Thursday, October 23, 2008

rsbaker0,

Thank you for quick response. I will appreciate a little bit more details, since as I said reflection is not my strong part (I've never worked with reflection before). The constructor for CSLA object is protected so I cannot instatiate the object with constructor but with a static method providing criteria (parameters) to fetch data. This part is pretty fogy for me, or beter said the syntax to invoke the get and invoke the method from CSLA object instantiated using reflection:

Activator.CreateInstance(_type, True)

Actually what I need explanation of following syntax:

System.Type _type = System.Type.GetType(strClassName, false, true);

Object o = null;
MethodInfo mi = null;
mi = _type.GetMethod(strMethodName, BindingFlags.Public Or BindingFlags.CreateInstance, Nothing, New Type() {_type}, Nothing)
o = mi.Invoke(oList, new object[] {criteria});

The syntax might be wrong but whatever I've tried didn't work or I don't see neither know how to fill in the blanks.

TIA,

geltendorf

rsbaker0 replied on Friday, October 24, 2008

Rocky has a MethodCaller in the CSLA infrastructure -- it would be worthwhile to look at it.

If you are manufacturing or retreiving object, usually you would be calling a static method.

For simple scenarios, you don't have to retrieve the MethodInfo. You can invoke the member by name.

Here are some examples (sorry it's C#).

object obj = ObjectType.InvokeMember("Get", System.Reflection.BindingFlags.FlattenHierarchy | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.InvokeMethod, null, null, new object[] { currentVal });

Or an entire function that calls GetEditableRootList (my static method) for a set of criteria:

 

public static IList GetEditableRootList(Type aType, string strFilter, string strSort, int pageSize, int pageIndex, params object[] parameters)

{

return (IList)aType.InvokeMember("GetEditableRootList", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null,

new object[] { strFilter, strSort, pageSize, pageIndex, parameters});

}

Copyright (c) Marimer LLC