I need to create an instance of an object and the type of that object will be determined at run time. The type of the object is pulled from SQL and set to a string value. I also need to pass a number of parameters when instantiating it. The number/type of parameters will be the same every time (for now at least). What do I need to use to accomplish this, Activator.CreateInstance? Any help would be appreciated.
private void StartScans(int scan_typeid, SqlDataReader drActiveServers)
{
string sql = "SELECT scan_typeclass from scan_types WHERE scan_typeid = " + scan_typeid.ToString();
sqlconn.Open();
SqlCommand cmd = new SqlCommand(sql, sqlconn);
SqlDataReader drScanClass = cmd.ExecuteReader(CommandBehavior.CloseConnection);
string scan_class = drScanClass["scan_typeclass"].ToString();
//Create object here
}
EDIT:
Richard Berg's solution worked in a console app but not in the above example, I've dumped scan_class and verified its getting a value however I keep getting this error:
System.ArgumentNullException: Value cannot be null. Parameter name: type
Here's what my updated code looks like:
try
{
string sql = "SELECT scan_typeclass from scan_types WHERE scan_typeid = " + scan_typeid.ToString();
sqlconn3.Open();
SqlCommand cmd = new SqlCommand(sql, sqlconn3);
SqlDataReader drScanClass = cmd.ExecuteReader();
drScanClass.Read();
string scan_class = drScanClass["scan_typeclass"].ToString();
var type = Type.GetType(scan_class);
var myObj = Activator.CreateInstance(type, scan_id, scan_name, interval, drActiveServers);
}
catch (Exception e)
{
string sSource = "SharedAuditSVC";
string sLog = "Application";
string sEvent = e.ToString();
if (!EventLog.SourceExists(sSource))
EventLog.CreateEventSource(sSource, sLog);
EventLog.WriteEntry(sSource, sEvent);
EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Warning, 0);
}
Meh, I think it's scope related though I have had no success calling my custom class through this method. I'll sleep on it.. :)
Works:
WindowsServiceAudit WSA = new WindowsServiceAudit(scan_id, scan_name, interval, drActiveServers);
Doesn't work:
string scan_class = "WindowsServiceAudit";
var type = Type.GetType(scan_class);
var myObj = Activator.CreateInstance(type, scan_id, scan_name, interval, drActiveServers);
Yes, exactly.
var type = Type.GetType(scan_class);
var myObject = Activator.CreateInstance(type, constructorArg1, constructorArg2, [...] );
// use myObject - you'll have to reflect on any properties that aren't derived from System.Object
EDIT
If the constructor is static or non-public, or the parameters you're passing create ambiguity in the constructors' overload resolution, then you'll need to use MethodInfo.Invoke() instead of Activator.CreateInstance().
var scan_class = "WindowsServiceAudit";
var bindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
var constructorArgs = new object[] { scan_id, scan_name, interval, drActiveServers };
var constructorTypes = from p in constructorArgs select p.GetType();
var type = Type.GetType(scan_class);
var method = type.GetMethod(scan_class, bindingFlags, System.Type.DefaultBinder, constructorTypes.ToArray(), null);
var myObject = method.Invoke(null, bindingFlags, System.Type.DefaultBinder, constructorArgs, CultureInfo.CurrentCulture);
Also make sure that:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With