[英]c# .NET runtime object type
我需要創建一個對象的實例,並且該對象的類型將在運行時確定。 對象的類型從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
}
編輯:
理查德·貝格(Richard Berg)的解決方案在控制台應用程序中工作,但在以上示例中不起作用,我轉儲了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);
}
嗯,我認為這與范圍有關,盡管我沒有通過這種方法成功調用自定義類。 我會睡覺的.. :)
作品:
WindowsServiceAudit WSA = new WindowsServiceAudit(scan_id, scan_name, interval, drActiveServers);
不起作用:
string scan_class = "WindowsServiceAudit";
var type = Type.GetType(scan_class);
var myObj = Activator.CreateInstance(type, scan_id, scan_name, interval, drActiveServers);
對,就是這樣。
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
編輯
如果構造函數是靜態的或非公共的,或者要傳遞的參數在構造函數的重載分辨率中造成歧義,那么您將需要使用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);
還要確保:
構造函數不是靜態的,而是公共的。 我嘗試了理查德的第二個建議,但是沒有運氣,另一個是空對象錯誤。
System.NullReferenceException:對象引用未設置為對象的實例。 在C:\\ shared_audit \\ SVC \\ SharedAuditSVC \\ SharedAuditSVC \\ Scan.cs:line 84的SharedAuditSVC.Scan.StartScans(Int32 scan_id,字符串scan_name,Int32 scan_typeid,Int32間隔,SqlDataReader drActiveServers)
第84行是:
var method = type.GetMethod(scan_class, bindingFlags, System.Type.DefaultBinder, constructorTypes.ToArray(), null);
我顯然在做一些可怕的錯誤,因為它沒有得到“ WindowsServiceAudit”的類型。 該項目是Windows服務,我的問題涉及2個.cs源文件Scan.cs和WindowsServiceAudit.cs。 Scan.cs是提取我所有代碼段的位置,WindowsServiceAudit是我要實例化的類。
namespace SharedAuditSVC
{
class Scan
{
namespace SharedAuditSVC
{
public class WindowsServiceAudit
{
兩者都是同一個命名空間的一部分,所以確實讓我感到困惑。 我也嘗試將其引用為SharedAuditSVC.WindowsServiceAudit
再次明確一點,我可以通過執行以下操作來創建它:
WindowsServiceAudit WSA = new WindowsServiceAudit(scan_id, scan_name, interval, drActiveServers);
終於正確了:)
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(CommandBehavior.CloseConnection);
drScanClass.Read();
var scan_class = "SharedAuditSVC." + drScanClass["scan_typeclass"].ToString();
Type[] argTypes = new Type[] { typeof(System.Int32), typeof(System.String), typeof(System.Int32), typeof(System.Data.SqlClient.SqlDataReader) };
object[] argVals = new object[] { scan_id, scan_name, scan_typeid, drActiveServers };
var type = Type.GetType(scan_class);
ConstructorInfo cInfo = type.GetConstructor(argTypes);
var myObject = cInfo.Invoke(argVals);
現在,我什至可以最終使args動態化。 謝謝您的幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.