Tạo một thể hiện của một lớp từ một chuỗi


217

Có cách nào để tạo một thể hiện của một lớp dựa trên thực tế tôi biết tên của lớp khi chạy. Về cơ bản tôi sẽ có tên của lớp trong một chuỗi.


Bạn dường như đã mô tả giải pháp bạn muốn thực hiện, nhưng không phải là vấn đề bạn đang cố gắng giải quyết. Có lẽ bạn đang cố gắng làm một cái gì đó với khả năng mở rộng, trong trường hợp đó tôi khuyên bạn nên kiểm tra Khung mở rộng được quản lý .
Jay Bazuzi

Câu trả lời:


159

Hãy xem phương thức Activator.CreateInstance .


15
Liên quan với các ví dụ tuyệt vời: stackoverflow.com/questions/493490/ Kẻ
John S.

Ngoài ra bài đăng này cũng sẽ có liên quan, vì loại của bạn cần được tìm thấy: stackoverflow.com/questions/1825147/ Kẻ
Công viên Brad


4
Ví dụ:var driver = (OpenQA.Selenium.IWebDriver)Activator.CreateInstance("WebDriver", "OpenQA.Selenium.Firefox.FirefoxDriver").Unwrap();
Endy Tjahjono

2
Lưu ý quan trọng ở đây: .Unwrap () để vượt qua tay cầm điều khiển từ xa để bạn thực sự có thể thực hiện các phôi. @Endy - Cảm ơn
Roger Willcocks

77

Nó khá đơn giản. Giả sử rằng tên lớp của bạn là Carvà không gian tên là Vehicles, sau đó truyền tham số như Vehicles.Cartrả về đối tượng kiểu Car. Như thế này, bạn có thể tạo bất kỳ trường hợp nào của bất kỳ lớp nào một cách linh hoạt.

public object GetInstance(string strFullyQualifiedName)
{         
     Type t = Type.GetType(strFullyQualifiedName); 
     return  Activator.CreateInstance(t);         
}

Nếu Tên đủ điều kiện của bạn (nghĩa là Vehicles.Cartrong trường hợp này) nằm trong một hội đồng khác, thì Type.GetTypenó sẽ là null. Trong những trường hợp như vậy, bạn có vòng lặp thông qua tất cả các hội đồng và tìm Type. Cho rằng bạn có thể sử dụng mã dưới đây

public object GetInstance(string strFullyQualifiedName)
{
     Type type = Type.GetType(strFullyQualifiedName);
     if (type != null)
         return Activator.CreateInstance(type);
     foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
     {
         type = asm.GetType(strFullyQualifiedName);
         if (type != null)
             return Activator.CreateInstance(type);
     }
     return null;
 }

Bây giờ nếu bạn muốn gọi một hàm tạo tham số, hãy làm như sau

Activator.CreateInstance(t,17); // Incase you are calling a constructor of int type

thay vì

Activator.CreateInstance(t);

Làm thế nào để sử dụng nó mà không cần truyền và làm thế nào để thực hiện việc truyền từ chuỗi đã cho ??
TaW

1
@TaW - để sử dụng một thể hiện của lớp, bạn sẽ cần có một số kiến ​​thức về những gì nó sẽ làm - nếu không bạn sẽ không thể sử dụng nó. Trường hợp sử dụng phổ biến nhất cho trường hợp này sẽ được truyền tới một số giao diện cung cấp cho bạn một hợp đồng được xác định trước. (Điều này giữ trừ khi bạn đang sử dụng dynamicmã - xem stackoverflow.com/a/2690661/904521 )
Tomer Cagan

1
Đừng mã hóa loại biến trong tên của nó. Ví dụ: không cần tiền tố strFullyQualifiedNamevới str, fullyQualifiedNamesẽ thực hiện công việc.
Mehdi Dehghani

Từ khóa strđược sử dụng như một phần của quy ước đặt tên cho các biến. Một số tổ chức và dự án nhất định tuân theo điều này, do đó tôi đã sử dụng. Nếu bạn đã từng làm việc trong một số dự án / dự án nhất định, bạn sẽ biết điều này. Như bạn đã nói mà không strcó nó cũng sẽ thực hiện công việc :) @MehdiDehghani
Sarath Avanavu

1
Tôi biết, không cần phải làm việc trong bất kỳ tổ chức nào để biết về quy ước đặt tên, tuy nhiên, quy ước này được gọi là ký hiệu Hungary và đó là một trong những quy ước đặt tên xấu và không được chấp nhận ngoài kia. đặc biệt dành cho C #
Mehdi Dehghani

55

Tôi đã sử dụng phương pháp này thành công:

System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(string className)

Bạn sẽ cần truyền đối tượng trả về loại đối tượng bạn muốn.


9
Tôi đang cố gắng tưởng tượng một kịch bản trong đó việc tạo đối tượng thông qua tên lớp và sau đó chuyển nó thành kiểu đó sẽ có ý nghĩa gì cả.
MusiGenesis

13
Tôi hiểu ý bạn là gì. Có vẻ dư thừa. Nếu bạn biết tên lớp, tại sao bạn cần chuỗi động? Một tình huống có thể là việc bạn truyền tới một lớp cơ sở và chuỗi đại diện cho hậu duệ của lớp cơ sở đó.
Ray Li

4
Nếu lớp cơ sở được biết đến, bạn có thể sử dụng lớp cơ sở hoặc giao diện của nó làm đối số để truyền con cháu mà không cần phản chiếu.
Garet Claborn

3
Kịch bản hữu ích: bạn chỉ cần các giao diện tuần tự hóa, hoặc bất kỳ giao diện khá phổ biến nào khác. Bạn sẽ không ném nó đến lớp, nhưng ít nhất là với một thứ không chỉ là một vật thể
Harald Coppoolse

2
Làm thế nào để thực hiện các diễn viên từ chuỗi đã cho ??
TaW

23

Có lẽ câu hỏi của tôi nên được cụ thể hơn. Tôi thực sự biết một lớp cơ sở cho chuỗi nên đã giải quyết nó bằng cách:

ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass));

Lớp Activator.CreateInstance có nhiều phương thức khác nhau để đạt được điều tương tự theo những cách khác nhau. Tôi có thể đã ném nó vào một đối tượng nhưng ở trên có ích nhất cho tình huống của tôi.


4
Thay vì trả lời trong phần câu hỏi, tôi sẽ đề nghị bạn chỉnh sửa câu hỏi của bạn và lưu ý các thay đổi. Bạn sẽ nhận được nhiều hơn / câu trả lời tốt hơn để làm điều đó.
Jason Jackson

Cảm ơn bạn đã đăng dòng mã cụ thể làm việc cho bạn. Sắp xếp qua tất cả các tình trạng quá tải của CreatInstance và các cách khác nhau để tạo Loại đã khiến tôi mất rất nhiều thời gian, điều mà bạn đã tiết kiệm cho tôi.
Ethel Evans

4

Tôi biết tôi đến trễ trò chơi ... nhưng giải pháp bạn đang tìm kiếm có thể là sự kết hợp của những điều trên và sử dụng một giao diện để xác định các đối tượng của bạn có thể truy cập công khai.

Sau đó, nếu tất cả các lớp của bạn sẽ được tạo theo cách này thực hiện giao diện đó, bạn có thể chỉ cần chọn làm loại giao diện và làm việc với đối tượng kết quả.


4

Để tạo một thể hiện của một lớp từ một dự án khác trong giải pháp, bạn có thể lấy cụm được chỉ định bằng tên của bất kỳ lớp nào (ví dụ BaseEntity) và tạo một thể hiện mới:

  var newClass = System.Reflection.Assembly.GetAssembly(typeof(BaseEntity)).CreateInstance("MyProject.Entities.User");

3

Ví dụ: nếu bạn lưu trữ các giá trị của các loại khác nhau trong trường cơ sở dữ liệu (được lưu dưới dạng chuỗi) và có một trường khác có tên loại (ví dụ: Chuỗi, bool, int, MyClass), thì từ dữ liệu trường đó, bạn có thể, có thể hiểu được, tạo một lớp của bất kỳ loại nào bằng cách sử dụng đoạn mã trên và điền vào nó với giá trị từ trường đầu tiên. Điều này tất nhiên phụ thuộc vào loại bạn đang lưu trữ có một phương pháp để phân tích các chuỗi thành đúng loại. Tôi đã sử dụng điều này nhiều lần để lưu trữ cài đặt tùy chọn người dùng trong cơ sở dữ liệu.


-11
ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass));

Tại sao bạn muốn viết một mã như thế này? Nếu bạn có sẵn một lớp 'Báo cáo', bạn có thể khởi tạo nó trực tiếp như hiển thị bên dưới.

ReportClass report = new ReportClass();

ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass));được sử dụng khi bạn không có sẵn lớp cần thiết, nhưng bạn muốn khởi tạo và hoặc gọi một phương thức một cách linh hoạt.

Tôi có nghĩa là nó hữu ích khi bạn biết lắp ráp nhưng trong khi viết mã, bạn không có lớp ReportClasscó sẵn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.