क्या मैं रनटाइम पर एक .NET असेंबली लोड कर सकता हूं और केवल नाम जानने के लिए एक प्रकार को त्वरित कर सकता हूं?


178

यदि प्रोजेक्ट में असेंबली का संदर्भ जोड़े बिना केवल DLL का नाम और वर्ग का नाम है, तो क्या रनटाइम के दौरान किसी ऑब्जेक्ट को इंस्टेंट करना संभव है? कक्षा एक इंटरफ़ेस को लागू करती है, इसलिए एक बार जब मैं कक्षा को तुरंत हटा देता हूं, तो मैं इसे इंटरफ़ेस पर डाल दूंगा।

विधानसभा का नाम:

library.dll

नाम लिखो:

Company.Project.Classname


संपादित करें: मैं DLL का पूर्ण पथ Assembly.LoadFileनहीं है , इसलिए काम नहीं करेगा। DLL एप्लिकेशन रूट, सिस्टम 32 या GAC में लोड किया जा सकता है।

जवाबों:


221

हाँ। आपको Assembly.LoadFromमेमोरी में असेंबली को लोड करने के लिए उपयोग करने की आवश्यकता है , फिर आप Activator.CreateInstanceअपने पसंदीदा प्रकार का एक उदाहरण बनाने के लिए उपयोग कर सकते हैं । आपको पहले प्रतिबिंब का उपयोग करके प्रकार देखना होगा। ये रहा एक सरल उदाहरण:

Assembly assembly = Assembly.LoadFrom("MyNice.dll");

Type type = assembly.GetType("MyType");

object instanceOfMyType = Activator.CreateInstance(type);

अपडेट करें

जब आपके पास असेंबली फ़ाइल का नाम और प्रकार का नाम होता है, तो आप Activator.CreateInstance(assemblyName, typeName)उस प्रकार में हल करने के लिए .NET टाइप रिज़ॉल्यूशन पूछने के लिए उपयोग कर सकते हैं । आप इसे एक कोशिश / पकड़ के साथ लपेट सकते हैं ताकि अगर यह विफल हो जाए, तो आप उन निर्देशिकाओं की खोज कर सकते हैं जहां आप विशेष रूप से अतिरिक्त असेंबलियों को संग्रहीत कर सकते हैं जो अन्यथा खोजे नहीं जा सकते हैं। यह उस बिंदु पर पूर्ववर्ती विधि का उपयोग करेगा।


2
मेरे पास dll का पूर्ण पथ नहीं है, इसलिए assemlby.LoadFile ect है। अभ्यस्त काम, कोई अन्य विचार?
मेगाबाइट

@ आरपी हमेशा मदद करने के लिए खुश है (और ऐसा कहने में केवल एक साल देर हो गई!)
जेफ

2
@MegaByte: LoadFrom LoadFile के लिए अलग है। यह आपकी निर्भरता को हल करेगा और यह ज्ञात पथ (GAC, exe निर्देशिका, आदि) से DLL नाम को हल करना चाहिए। अधिक जानकारी के लिए MSDN देखें।
जेफ येट्स

1
एक और बात ... (मुझे फिर से) उम, आप केवल "MyType" टाइप नाम के रूप में नहीं कर सकते, इसे NAMESPACE द्वारा अनुसरण किया जाना चाहिए। तो यह अधिक सटीक होगा:Type type = assembly.GetType("MyNamespace"+"."+"MyType");
सिपि

1
@Cipi: तकनीकी रूप से, यह एक प्रकार पूर्ण नाम नाम है (नाम स्थान की अवधारणा एक भाषा सुविधा है)। आपके पास CLR के भीतर कोई नामस्थान नहीं हो सकता है - मैं सिर्फ एक अत्यधिक सरलीकृत उदाहरण प्रदान कर रहा था।
जेफ येट्स

36

विभिन्न Load*तरीकों की सीमाओं पर विचार करें । से MSDN डॉक्स ...

LoadFile LoadFrom संदर्भ में फ़ाइलों को लोड नहीं करता है, और लोड पथ का उपयोग करके निर्भरता को हल नहीं करता है, जैसा कि LoadFrom विधि करता है।

LoadFromडॉक्स में लोड कॉन्टेक्ट्स के बारे में अधिक जानकारी पाई जा सकती है ।


19

Activator.CreateInstance को काम करना चाहिए।

IFace object = (IFace)Activator.CreateInstance( "AssemblyName",
                                                "TypeName" )
                               .Unwrap();

नोट: प्रकार नाम पूरी तरह से योग्य होना चाहिए।

उदाहरण:

var aray = (IList)Activator.CreateInstance("mscorlib","System.Collections.ArrayList").Unwrap();
aray.Add(10);

foreach (object obj in aray)
{
    Console.WriteLine(obj);
}

1
बस इस पर एक नोट: TypeNameपूरी तरह से योग्य होना चाहिए। मुझे इसे कॉल करना था: Activator.CreateInstance("MyAssembly","MyAssembly.TypeName") और वह रिटर्न ए ObjectHandle। अपने इंटरफ़ेस से नीचे उतरने के लिए आपको करने की आवश्यकता हैObjectHandle.UnWrap()
एंथोनी सॉटाइल

7

मुझे यह प्रश्न और कुछ उत्तर बहुत उपयोगी लगे, हालाँकि मुझे पथ की समस्या थी, इसलिए यह उत्तर बिन निर्देशिका पथ को खोजकर लोडिंग लाइब्रेरी को कवर करेगा।

पहला उपाय:

string assemblyName = "library.dll";
string assemblyPath = HttpContext.Current.Server.MapPath("~/bin/" + assemblyName);
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Type T = assembly.GetType("Company.Project.Classname");
Company.Project.Classname instance = (Company.Project.Classname) Activator.CreateInstance(T);

दूसरा उपाय

string assemblyName = "library.dll";
string assemblyPath = HttpContext.Current.Server.MapPath("~/bin/" + assemblyName);
Assembly assembly = Assembly.LoadFile(assemblyPath);
(Company.Project.Classname) instance = (Company.Project.Classname) assembly.CreateInstance("Company.Project.Classname");

आप इंटरफेस के लिए एक ही सिद्धांत का उपयोग कर सकते हैं (आप एक वर्ग बना रहे हैं लेकिन इंटरफ़ेस पर कास्टिंग करेंगे), जैसे:

(Company.Project.Interfacename) instance = (Company.Project.Interfacename) assembly.CreateInstance("Company.Project.Classname");

यह उदाहरण वेब एप्लिकेशन के लिए है लेकिन डेस्कटॉप एप्लिकेशन के लिए भी इसका उपयोग किया जा सकता है, उदाहरण के लिए, केवल पथ को अलग तरीके से हल किया जाता है

Path.GetDirectoryName(Application.ExecutablePath)

5

यह आसान है।

MSDN से उदाहरण:

public static void Main()
{
    // Use the file name to load the assembly into the current
    // application domain.
    Assembly a = Assembly.Load("example");
    // Get the type to use.
    Type myType = a.GetType("Example");
    // Get the method to call.
    MethodInfo myMethod = myType.GetMethod("MethodA");
    // Create an instance.
    object obj = Activator.CreateInstance(myType);
    // Execute the method.
    myMethod.Invoke(obj, null);
}

यहां एक संदर्भ लिंक दिया गया है

https://msdn.microsoft.com/en-us/library/25y1ya39.aspx


कोड के गतिशील लोडिंग का समर्थन करने के लिए यह एक भयानक तरीका है। MS ने हमेशा हमें बहुत अधिक विवरणों के लिए बाध्य करने के लिए पसंद किया है।
क्लीयर

3

फ्रेमवर्क v4.5 से शुरू करके आप विधानसभाओं के भीतर आसानी से कक्षाओं को तुरंत करने के लिए Activator.CreateInstanceFrom () का उपयोग कर सकते हैं । निम्नलिखित उदाहरण से पता चलता है कि इसका उपयोग कैसे करें और कैसे एक विधि पासिंग मापदंडों को कॉल करें और रिटर्न वैल्यू प्राप्त करें।

    // Assuming moduleFileName contains full or valid relative path to assembly    
    var moduleInstance = Activator.CreateInstanceFrom(moduleFileName, "MyNamespace.MyClass");
    MethodInfo mi = moduleInstance.Unwrap().GetType().GetMethod("MyMethod");
    // Assuming the method returns a boolean and accepts a single string parameter
    bool rc = Convert.ToBoolean(mi.Invoke(moduleInstance.Unwrap(), new object[] { "MyParamValue" } ));

2

हाँ। मेरे पास कोई उदाहरण नहीं है जो मैंने व्यक्तिगत रूप से अभी उपलब्ध कराया है। जब मुझे कुछ मिलेगा तो बाद में पोस्ट करूँगा। मूल रूप से आप असेंबली को लोड करने के लिए प्रतिबिंब का उपयोग करेंगे और फिर इसके लिए आपको जो भी प्रकार की आवश्यकता होगी, उसे खींचने के लिए।

इस बीच, यह लिंक आपको शुरू कर देना चाहिए:

रनटाइम पर अप्रकाशित विधानसभाओं को लोड करने के लिए प्रतिबिंब का उपयोग करना


2
((ISomeInterface)Activator.CreateInstance(Assembly.LoadFile("somePath").GetTypes()[0])).SomeInterfaceMethod();

2

आप एक विधानसभा का उपयोग कर लोड कर सकते हैं। Activator.CreateInstance का उपयोग करके आप अपने इच्छित प्रकार के नए उदाहरण बना सकते हैं। ध्यान रखें कि आपको उस वर्ग के पूर्ण प्रकार के नाम का उपयोग करना होगा जिसे आप लोड करना चाहते हैं (उदाहरण के लिए Namespace.SubNamespace.ClassName )। पद्धति का उपयोग करना InvokeMember का प्रकार वर्ग आप प्रकार पर विधियां प्रारंभ कर सकते हैं।

यह भी ध्यान में रखें कि एक बार लोड होने पर, एक असेंबली को तब तक लोड नहीं किया जा सकता जब तक कि पूरे AppDomain को भी उतार न दिया जाए (यह मूल रूप से मेमोरी लीक है)।


2

इस तरह की कार्यक्षमता आपकी परियोजना के लिए कितनी आंतरिक है, इसके आधार पर, आप एमईएफ जैसी किसी चीज पर विचार करना चाह सकते हैं जो आपके लिए घटकों के एक साथ लोडिंग और बांधने का ख्याल रखेगा।


2
Assembly assembly = Assembly.LoadFrom("MyAssembly.dll");

Type type = assembly.GetType("MyType");

dynamic instanceOfMyType = Activator.CreateInstance(type);

तो इस तरह से आप कार्यप्रणाली को प्राप्त नहीं करने के साथ कार्यों का उपयोग कर सकते हैं, और फिर इसे लागू कर सकते हैं। आप इस उदाहरण को पसंद करेंगे। OfMyType.MethodName (); लेकिन आप Intellisense का उपयोग नहीं कर सकते क्योंकि गतिशील प्रकार रनटाइम में टाइप किए जाते हैं, संकलन समय में नहीं।


1

हां, यह है, आप असेंबली क्लास पर स्थिर लोड विधि का उपयोग करना चाहते हैं, और फिर कॉल करें कॉल असेंबली विधि असेंबली इंस्टेंस पर आपको कॉल से लोड करने के लिए वापस आ गया।

इसके अलावा, आप अपनी आवश्यकताओं के आधार पर असेंबली वर्ग पर "लोड" से शुरू होने वाले अन्य स्थिर तरीकों में से एक को कॉल कर सकते हैं।


0

आप इस तरह से इस काम को कर सकते हैं:

using System.Reflection;

Assembly MyDALL = Assembly.Load("DALL"); //DALL name of your assembly
Type MyLoadClass = MyDALL.GetType("DALL.LoadClass"); // name of your class
 object  obj = Activator.CreateInstance(MyLoadClass);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.