Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# .NET runtime object type

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);
like image 707
jw0rd Avatar asked Aug 15 '26 11:08

jw0rd


1 Answers

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:

  1. The type name is fully qualified. Reflection doesn't know anything about "using" statements.
  2. The assembly where the type resides is loaded. Use Assembly.Load() if necessary.
like image 126
Richard Berg Avatar answered Aug 17 '26 00:08

Richard Berg



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!