Activator.CreateInstance का उद्देश्य उदाहरण के साथ?


124

क्या कोई Activator.CreateInstance()उद्देश्य के बारे में विस्तार से बता सकता है?


6
संभवतः यह अधिक से अधिक प्रलेखन और उदाहरण जेनेरिक अधिभार में उपलब्ध नहीं है। मैं प्रोत्साहित करूंगा कि ओवरलोड के CreateInstance(Type type)साथ प्रलेखन से मिलान किया CreateInstance<T>()जाए।
क्लॉस जोर्जेंसन

4
MSDN पृष्ठ में केवल एक व्याख्यात्मक पंक्ति है, "स्थानीय या दूरस्थ रूप से ऑब्जेक्ट्स के प्रकार बनाने या मौजूदा दूरस्थ ऑब्जेक्ट्स के संदर्भ प्राप्त करने के लिए तरीके शामिल हैं। इस वर्ग को विरासत में नहीं मिला जा सकता है।" msdn.microsoft.com/en-us/library/system.activator.aspx
gonzobrains

2
यदि आप जावा बैकग्राउंड से यहां आए हैं, तो यह c#.netकरने का तरीका है Object xyz = Class.forName(className).newInstance();
एसएनजी

यहाँ इसके लिए बेहतर प्रलेखन है
jpaugh

जवाबों:


149

कहो कि आपके पास MyFancyObjectनीचे इस तरह एक वर्ग है :

class MyFancyObject
{
 public int A { get;set;}
}

यह आपको मुड़ने देता है:

String ClassName = "MyFancyObject";

में

MyFancyObject obj;

का उपयोग करते हुए

obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))

और फिर सामान की तरह कर सकते हैं:

obj.A = 100;

यही इसका उद्देश्य है। इसमें कई अन्य अधिभार भी हैं जैसे कि Typeएक स्ट्रिंग में वर्ग नाम के बजाय प्रदान करना । क्यों आपको एक समस्या होगी जैसे कि एक अलग कहानी है। यहाँ कुछ लोग हैं जिन्हें इसकी आवश्यकता है:


2
यह मेरे लिए उपयोगी साबित हुआ। मेरे मामले में, क्लास एक अलग नामस्थान में थी, इसलिए मुझे यह सुनिश्चित करना था कि मैं अपने क्लासनाम स्ट्रिंग (यानी String ClassName = "My.Namespace.MyFancyObject";) में नामस्थान को शामिल करूं ।
स्कॉट

1
आप Unwrap () जोड़ना भूल गए। आप "MyAssembly" के बजाय नल भी डाल सकते हैं, और सिस्टम वर्तमान विधानसभा की खोज करेगा।
टोनी

1
क्या मैं ऐसा कुछ कर सकता हूं, obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))लेकिन टाइप के साथ कास्टिंग करने के बजाय। ClassName से बने प्रकार के साथ कास्ट करें? इस तरह Type type = Type.GetType(ClassName);obj = (type )Activator.CreateInstance("MyAssembly", ClassName))?
rluks

1
उपरोक्त कैसे अलग है: MyFancyObject obj = new MyFancyObject?
एड लैंडौ

1
@Ed Landau अंतर यह है कि आप किसी ऑब्जेक्ट को रन टाइम पर इंस्टेंट कर सकते हैं, जिसे आप नहीं जानते कि यह संकलन के समय टाइप है। उदाहरण के लिए यदि आप अपने प्रोग्राम के लिए एक प्लगइन सिस्टम बना रहे थे। जवाब में दिए लिंक आपको कुछ विचार दे सकते हैं जब यह संभव नहीं होगा कि आप सिर्फ MyFancyObject obj = new MyFancyObject () लिखें। यह अक्सर सामान्य रूप से प्रतिबिंब के उपयोग के साथ जोड़ा जाएगा। आप अभी तक एक अन्य विवरण के लिए stackoverflow.com/questions/9409293/… देख सकते हैं ।
दीप

47

वैसे मैं आपको एक उदाहरण दे सकता हूं कि ऐसा कुछ क्यों इस्तेमाल किया जाए। एक गेम के बारे में सोचें जहां आप अपने स्तर और दुश्मनों को एक्सएमएल फाइल में स्टोर करना चाहते हैं। जब आप इस फ़ाइल को पार्स करते हैं, तो आपके पास इस तरह का एक तत्व हो सकता है।

<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>

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

foreach(XmlNode node in doc)
   var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);

गतिशील एनवायरमेंट बनाने के लिए यह बहुत उपयोगी है। बेशक, इसका उपयोग प्लगिन या एडिन परिदृश्यों के लिए भी करना संभव है और बहुत अधिक।


5
मैं समझ गया कि यह एक प्रकार का नया उदाहरण बनाना है, लेकिन यह एक अच्छा सरल उदाहरण है कि कोई ऐसा क्यों करना चाहेगा।
जैमीबारो

14

मेरा अच्छा दोस्त 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

1
MSDN के लिए होने के लिए, और यहाँ सामग्री कॉपी की संभावना नहीं है लगभग ); कॉपीराइट का उल्लंघन
क्लॉस Jørgensen

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

10

आप यह भी कर सकते हैं -

var handle = Activator.CreateInstance("AssemblyName", 
                "Full name of the class including the namespace and class name");
var obj = handle.Unwrap();

अनपराप () लापता टुकड़ा था। :)
टोनी

मैं 'Unwrap ()' विधि का उपयोग करने के लिए ऊपर नहीं पा सकता (जैसा कि ऊपर)। क्या नए .NET API में कुछ बदला गया है?
सैम

यह अभी भी सिस्टम नेमस्पेस में है।
विलियम

2
क्या आप इस बारे में कुछ अतिरिक्त स्पष्टीकरण प्रदान कर सकते हैं कि .Unwrap()यह क्या करता है और यह अन्य समाधानों से कैसे संबंधित है?
जीरो वेनवेल

@ यह एक अलग ओवरलोड पर है CreateInstanceजहाँ यह वापस आता है System.Runtime.Remoting.ObjectHandle
नवाफल

9

एक अच्छा उदाहरण अगले हो सकता है: उदाहरण के लिए आपके पास लकड़हारा का एक सेट है और आप उपयोगकर्ता को कॉन्फ़िगरेशन फ़ाइल के माध्यम से रनटाइम में उपयोग किए जाने वाले प्रकार को निर्दिष्ट करने की अनुमति देते हैं।

फिर:

string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;

या एक अन्य मामला यह है कि जब आपके पास एक सामान्य इकाइयां कारखाना होता है, जो इकाई बनाता है, और डीएम से प्राप्त डेटा द्वारा एक इकाई के प्रारंभ पर भी जिम्मेदार होता है:

(स्यूडोकोड)

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
Barkermn01

3

Activator.CreateInstance विधि एक निर्दिष्ट प्रकार का निर्माण करती है, जिसमें कंस्ट्रक्टर का उपयोग किया जाता है जो निर्दिष्ट मापदंडों से सर्वोत्तम रूप से मेल खाता है।

उदाहरण के लिए, मान लें कि आपके पास स्ट्रिंग के रूप में नाम है, और आप उस प्रकार का उदाहरण बनाने के लिए स्ट्रिंग का उपयोग करना चाहते हैं। आप इसके लिए उपयोग कर सकते हैं Activator.CreateInstance:

string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));

यहाँ एक MSDN आलेख है जो यह बताता है कि यह अधिक विस्तार से अनुप्रयोग है:

http://msdn.microsoft.com/en-us/library/wccyzw83.aspx


5
या आप बस इस्तेमाल कर सकते हैं new Foo()। मुझे लगता है कि ओपी एक अधिक यथार्थवादी उदाहरण चाहता था।
कोनराड रुडोल्फ

1
मैं @ कोनराड से सहमत हूं। उपयोग करने का कारण यह CreateInstanceहै कि यदि आप डिजाइन के समय पर ऑब्जेक्ट के प्रकार को नहीं जानते हैं, तो आप तुरंत जा सकते हैं। इस उदाहरण में, आप स्पष्ट रूप से जानते हैं कि यह प्रकार है Fooक्योंकि आप इसे टाइप कर रहे हैं Foo। आप ऐसा कभी नहीं करेंगे क्योंकि आप बस कर सकते हैंFoo foo = new Foo()
थेटिमैन

1

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

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);

0

यदि आप पहले से ही वर्ग को जानते हैं और इसे कास्ट करने जा रहे हैं तो आप इसका उपयोग क्यों करेंगे? सिर्फ पुराने तरीके से ही क्यों न करें और कक्षा को हमेशा की तरह बना लें? इस तरह से इसका कोई फायदा नहीं है क्योंकि यह सामान्य रूप से किया जाता है। क्या इस तरह से पाठ लेने और उस पर काम करने का कोई तरीका है:

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();

लेकिन मुझे लगता है कि अगर यह मौजूद है तो मैजिक पद्धति का एक बड़ा फायदा होगा।


0

परावर्तन के साथ युग्मित, मुझे Activator.CreateInstance मिला, जो संग्रहीत कार्यविधि को मैप करने में बहुत सहायक होता है, जिसका परिणाम निम्न उत्तर में वर्णित एक कस्टम वर्ग के लिए होता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.