ใครช่วยอธิบายActivator.CreateInstance()
วัตถุประสงค์โดยละเอียดได้ไหม
c#.net
Object xyz = Class.forName(className).newInstance();
ใครช่วยอธิบายActivator.CreateInstance()
วัตถุประสงค์โดยละเอียดได้ไหม
c#.net
Object xyz = Class.forName(className).newInstance();
คำตอบ:
สมมติว่าคุณมีคลาสที่เรียกMyFancyObject
แบบนี้ด้านล่าง:
class MyFancyObject
{
public int A { get;set;}
}
ช่วยให้คุณเปิด:
String ClassName = "MyFancyObject";
เข้าไป
MyFancyObject obj;
การใช้
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
จากนั้นสามารถทำสิ่งต่างๆเช่น:
obj.A = 100;
นั่นคือจุดประสงค์ นอกจากนี้ยังมีโอเวอร์โหลดอื่น ๆ อีกมากมายเช่นการType
ระบุชื่อคลาสในสตริง ทำไมคุณถึงมีปัญหาเช่นนั้นเป็นเรื่องที่แตกต่างกัน นี่คือบางคนที่ต้องการ:
String ClassName = "My.Namespace.MyFancyObject";
)
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
ได้ไหม แต่แทนที่จะหล่อด้วยไทป์ แคสต์ด้วยประเภทที่สร้างจาก ClassName? แบบนี้Type type = Type.GetType(ClassName);obj = (type )Activator.CreateInstance("MyAssembly", ClassName))
เหรอ?
ฉันจะยกตัวอย่างให้คุณได้ว่าทำไมต้องใช้อะไรแบบนั้น ลองนึกถึงเกมที่คุณต้องการเก็บเลเวลและศัตรูไว้ในไฟล์ XML เมื่อคุณแยกวิเคราะห์ไฟล์นี้คุณอาจมีองค์ประกอบเช่นนี้
<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>
สิ่งที่คุณทำได้ตอนนี้คือสร้างวัตถุแบบไดนามิกที่พบในไฟล์ระดับของคุณ
foreach(XmlNode node in doc)
var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);
สิ่งนี้มีประโยชน์มากสำหรับการสร้างสภาพแวดล้อมแบบไดนามิก แน่นอนว่ามันเป็นไปได้ที่จะใช้สิ่งนี้สำหรับสถานการณ์ปลั๊กอินหรือ addin และอื่น ๆ อีกมากมาย
MSDN เพื่อนที่ดีของฉันสามารถอธิบายให้คุณฟังด้วยตัวอย่าง
นี่คือรหัสในกรณีที่ลิงก์หรือเนื้อหามีการเปลี่ยนแปลงในอนาคต:
using System;
class DynamicInstanceList
{
private static string instanceSpec = "System.EventArgs;System.Random;" +
"System.Exception;System.Object;System.Version";
public static void Main()
{
string[] instances = instanceSpec.Split(';');
Array instlist = Array.CreateInstance(typeof(object), instances.Length);
object item;
for (int i = 0; i < instances.Length; i++)
{
// create the object from the specification string
Console.WriteLine("Creating instance of: {0}", instances[i]);
item = Activator.CreateInstance(Type.GetType(instances[i]));
instlist.SetValue(item, i);
}
Console.WriteLine("\nObjects and their default values:\n");
foreach (object o in instlist)
{
Console.WriteLine("Type: {0}\nValue: {1}\nHashCode: {2}\n",
o.GetType().FullName, o.ToString(), o.GetHashCode());
}
}
}
// This program will display output similar to the following:
//
// Creating instance of: System.EventArgs
// Creating instance of: System.Random
// Creating instance of: System.Exception
// Creating instance of: System.Object
// Creating instance of: System.Version
//
// Objects and their default values:
//
// Type: System.EventArgs
// Value: System.EventArgs
// HashCode: 46104728
//
// Type: System.Random
// Value: System.Random
// HashCode: 12289376
//
// Type: System.Exception
// Value: System.Exception: Exception of type 'System.Exception' was thrown.
// HashCode: 55530882
//
// Type: System.Object
// Value: System.Object
// HashCode: 30015890
//
// Type: System.Version
// Value: 0.0
// HashCode: 1048575
คุณสามารถทำได้เช่นกัน -
var handle = Activator.CreateInstance("AssemblyName",
"Full name of the class including the namespace and class name");
var obj = handle.Unwrap();
.Unwrap()
แม่นยำและเกี่ยวข้องกับโซลูชันอื่น ๆ ได้อย่างไร
CreateInstance
System.Runtime.Remoting.ObjectHandle
ตัวอย่างที่ดีอาจเป็นตัวอย่างถัดไปเช่นคุณมี Loggers ชุดหนึ่งและคุณอนุญาตให้ผู้ใช้ระบุประเภทที่จะใช้ในรันไทม์ผ่านไฟล์กำหนดค่า
แล้ว:
string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;
หรืออีกกรณีหนึ่งคือเมื่อคุณมีโรงงานเอนทิตีทั่วไปซึ่งสร้างเอนทิตีและรับผิดชอบในการเริ่มต้นเอนทิตีด้วยข้อมูลที่ได้รับจาก DB:
(pseudocode)
public TEntity CreateEntityFromDataRow<TEntity>(DataRow row)
where TEntity : IDbEntity, class
{
MethodInfo methodInfo = typeof(T).GetMethod("BuildFromDataRow");
TEntity instance = Activator.CreateInstance(typeof(TEntity)) as TEntity;
return methodInfo.Invoke(instance, new object[] { row } ) as TEntity;
}
typeof(loggerType)
ผลในloggerType is a variable and used like a type
Activator.CreateInstance
วิธีการสร้างตัวอย่างของประเภทที่ระบุโดยใช้ตัวสร้างที่ตรงกับพารามิเตอร์ที่ระบุ
ตัวอย่างเช่นสมมติว่าคุณมีชื่อประเภทเป็นสตริงและคุณต้องการใช้สตริงเพื่อสร้างอินสแตนซ์ของประเภทนั้น คุณสามารถใช้Activator.CreateInstance
สำหรับสิ่งนี้:
string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));
นี่คือบทความ MSDN ที่อธิบายรายละเอียดเพิ่มเติมเกี่ยวกับแอปพลิเคชัน:
new Foo()
หรือคุณก็สามารถใช้ ฉันคิดว่า OP ต้องการตัวอย่างที่เป็นจริงมากขึ้น
CreateInstance
คือถ้าคุณไม่ทราบประเภทของวัตถุที่คุณจะสร้างอินสแตนซ์ในเวลาออกแบบ ในตัวอย่างนี้คุณรู้อย่างชัดเจนว่ามันเป็นประเภทตั้งแต่คุณหล่อมันเป็นประเภทFoo
คุณจะไม่ทำเช่นนี้เพราะคุณก็สามารถทำได้Foo
Foo foo = new Foo()
อาคารออกจาก deepee1 และนี้นี่เป็นวิธีที่จะยอมรับชื่อชั้นในสตริงแล้วใช้มันในการอ่านและการเขียนไปยังฐานข้อมูลที่มี LINQ ฉันใช้ "ไดนามิก" แทนการแคสต์ของ deepee1 เพราะทำให้ฉันสามารถกำหนดคุณสมบัติซึ่งทำให้เราสามารถเลือกและดำเนินการบนตารางใดก็ได้ที่เราต้องการแบบไดนามิก
Type tableType = Assembly.GetExecutingAssembly().GetType("NameSpace.TableName");
ITable itable = dbcontext.GetTable(tableType);
//prints contents of the table
foreach (object y in itable) {
string value = (string)y.GetType().GetProperty("ColumnName").GetValue(y, null);
Console.WriteLine(value);
}
//inserting into a table
dynamic tableClass = Activator.CreateInstance(tableType);
//Alternative to using tableType, using Tony's tips
dynamic tableClass = Activator.CreateInstance(null, "NameSpace.TableName").Unwrap();
tableClass.Word = userParameter;
itable.InsertOnSubmit(tableClass);
dbcontext.SubmitChanges();
//sql equivalent
dbcontext.ExecuteCommand("INSERT INTO [TableNme]([ColumnName]) VALUES ({0})", userParameter);
ทำไมคุณถึงใช้มันถ้าคุณรู้จักคลาสแล้วและกำลังจะแคสต์ ทำไมไม่ทำแบบเดิม ๆ และทำให้ชั้นเรียนเหมือนที่คุณทำอยู่เสมอ ไม่มีประโยชน์อะไรกับวิธีการทำตามปกติ มีวิธีที่จะใช้ข้อความและดำเนินการตามนี้:
label1.txt = "Pizza"
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();
ถ้าฉันรู้อยู่แล้วว่าพิซซ่าของมันไม่มีประโยชน์อะไรที่จะ:
p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();
แต่ฉันเห็นข้อได้เปรียบอย่างมากสำหรับเมธอด Magic หากมีอยู่
CreateInstance(Type type)
ตรงกับการCreateInstance<T>()
โอเวอร์โหลด