Ai đó có thể giải thích Activator.CreateInstance()
mục đích chi tiết?
c#.net
cách làm Object xyz = Class.forName(className).newInstance();
.
Ai đó có thể giải thích Activator.CreateInstance()
mục đích chi tiết?
c#.net
cách làm Object xyz = Class.forName(className).newInstance();
.
Câu trả lời:
Giả sử bạn có một lớp được gọi MyFancyObject
như thế này dưới đây:
class MyFancyObject
{
public int A { get;set;}
}
Nó cho phép bạn bật:
String ClassName = "MyFancyObject";
Vào
MyFancyObject obj;
Sử dụng
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
và sau đó có thể làm những thứ như:
obj.A = 100;
Đó là mục đích của nó. Nó cũng có nhiều tình trạng quá tải khác như cung cấp một Type
thay vì tên lớp trong một chuỗi. Tại sao bạn sẽ có một vấn đề như thế là một câu chuyện khác. Đây là một số người cần nó:
String ClassName = "My.Namespace.MyFancyObject";
).
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
nhưng thay vì đúc với các loại. Truyền với loại được làm từ ClassName? Như thế này Type type = Type.GetType(ClassName);obj = (type )Activator.CreateInstance("MyAssembly", ClassName))
?
Vâng, tôi có thể cho bạn một ví dụ tại sao sử dụng một cái gì đó như thế. Hãy nghĩ về một trò chơi mà bạn muốn lưu trữ cấp độ và kẻ thù của mình trong một tệp XML. Khi bạn phân tích tệp này, bạn có thể có một phần tử như thế này.
<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>
những gì bạn có thể làm bây giờ là, tạo động các đối tượng được tìm thấy trong tệp cấp của bạn.
foreach(XmlNode node in doc)
var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);
Điều này rất hữu ích, để xây dựng môi trường năng động. Tất nhiên cũng có thể sử dụng điều này cho các tình huống Plugin hoặc addin và nhiều hơn nữa.
MSDN, người bạn tốt của tôi có thể giải thích cho bạn, với một ví dụ
Đây là mã trong trường hợp liên kết hoặc nội dung thay đổi trong tương lai:
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
Bạn cũng có thể làm điều này -
var handle = Activator.CreateInstance("AssemblyName",
"Full name of the class including the namespace and class name");
var obj = handle.Unwrap();
.Unwrap()
chính xác và làm thế nào điều này liên quan đến các giải pháp khác?
CreateInstance
nơi nó trở lại System.Runtime.Remoting.ObjectHandle
.
Một ví dụ điển hình có thể là tiếp theo: ví dụ bạn có một bộ Loggers và bạn cho phép người dùng chỉ định loại sẽ được sử dụng trong thời gian chạy thông qua tệp cấu hình.
Sau đó:
string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;
HOẶC trường hợp khác là khi bạn có một nhà máy thực thể chung, tạo ra thực thể và cũng chịu trách nhiệm khởi tạo một thực thể bằng dữ liệu nhận được từ DB:
(mã giả)
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)
kết quả làloggerType is a variable and used like a type
Các Activator.CreateInstance
phương pháp tạo ra một thể hiện của một loại quy định sử dụng các nhà xây dựng phù hợp tốt nhất các thông số quy định.
Ví dụ: giả sử bạn có tên loại dưới dạng chuỗi và bạn muốn sử dụng chuỗi để tạo phiên bản của loại đó. Bạn có thể sử dụng Activator.CreateInstance
cho việc này:
string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));
Đây là một bài viết MSDN giải thích chi tiết hơn về ứng dụng của nó:
new Foo()
. Tôi nghĩ rằng OP muốn một ví dụ thực tế hơn.
CreateInstance
là nếu bạn không biết loại đối tượng bạn sẽ khởi tạo tại thời điểm thiết kế. Trong ví dụ này, bạn biết rõ loại của nó Foo
vì bạn đang chọn nó là loại Foo
. Bạn sẽ không bao giờ làm điều này bởi vì bạn chỉ có thể làm Foo foo = new Foo()
.
Xây dựng deepee1 và đây , đây là cách chấp nhận tên lớp trong chuỗi, sau đó sử dụng nó để đọc và ghi vào cơ sở dữ liệu với LINQ. Tôi sử dụng "động" thay vì truyền của deepee1 vì nó cho phép tôi gán các thuộc tính, cho phép chúng tôi tự động chọn và vận hành trên bất kỳ bảng nào chúng tôi muốn.
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);
Tại sao bạn sẽ sử dụng nó nếu bạn đã biết về lớp học và sẽ chọn nó? Tại sao không làm theo cách cũ và làm cho lớp như bạn luôn làm cho nó? Không có lợi thế cho điều này qua cách nó được thực hiện bình thường. Có cách nào để lấy văn bản và vận hành trên đó không:
label1.txt = "Pizza"
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();
Nếu tôi đã biết Pizza của nó thì không có lợi thế nào:
p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();
nhưng tôi thấy một lợi thế rất lớn cho phương pháp Phép thuật nếu nó tồn tại.
Kết hợp với sự phản chiếu, tôi thấy Activator.CreateInstance rất hữu ích trong việc ánh xạ kết quả thủ tục được lưu trữ vào một lớp tùy chỉnh như được mô tả trong câu trả lời sau .
CreateInstance(Type type)
phù hợp vớiCreateInstance<T>()
quá tải.