jw0*_*0rd 3 .net c# reflection
我需要创建一个对象的实例,该对象的类型将在运行时确定.从SQL中提取对象的类型并将其设置为字符串值.我还需要在实例化时传递一些参数.参数的数量/类型每次都相同(至少现在).我需要用什么来实现这一点,Activator.CreateInstance?任何帮助,将不胜感激.
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
}
Run Code Online (Sandbox Code Playgroud)
编辑:
理查德·伯格的解决方案在控制台应用程序中工作但不在上面的示例中,我已经转储了scan_class并验证了它获取值但是我一直收到此错误:
System.ArgumentNullException:值不能为null.参数名称:类型
这是我更新的代码:
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);
}
Run Code Online (Sandbox Code Playgroud)
嗯,我认为这与范围有关,虽然我没有成功通过这种方法调用我的自定义类.我会睡在它上面.. :)
作品:
WindowsServiceAudit WSA = new WindowsServiceAudit(scan_id, scan_name, interval, drActiveServers);
Run Code Online (Sandbox Code Playgroud)
不起作用:
string scan_class = "WindowsServiceAudit";
var type = Type.GetType(scan_class);
var myObj = Activator.CreateInstance(type, scan_id, scan_name, interval, drActiveServers);
Run Code Online (Sandbox Code Playgroud)
对,就是这样.
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
Run Code Online (Sandbox Code Playgroud)
编辑
如果构造函数是静态的或非公共的,或者您传递的参数在构造函数的重载决策中产生歧义,那么您将需要使用MethodInfo.Invoke()而不是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);
Run Code Online (Sandbox Code Playgroud)
还要确保: