2008-11-17 13 views
15

मेरे पास कक्षाओं का एक सेट है, वही काम करने के लिए प्रत्येक एक अलग strategy है।केवल कक्षा का नाम जानने वाले ऑब्जेक्ट बनाएं?

namespace BigCorp.SuperApp 
{ 
    public class BaseClass { } 
    public class ClassA : BaseClass { } 
    public class ClassB : BaseClass { } 
} 

उपयोग करने की कौन सी रणनीति का चयन कॉन्फ़िगर करने योग्य है। मैं app.config फ़ाइल में पूर्ण प्रकार के नाम 'BigCorp.SuperApp.ClassB' के बजाय केवल क्लास नाम 'क्लासबी' को कॉन्फ़िगर करना चाहता हूं।

<appConfig> 
    <SuperAppConfig> 
     <Handler name="ClassB" /> 
    </SuperAppConfig> 
</appConfig> 

हालांकि, प्रतिबिंब कॉल विफल क्योंकि वे पूर्ण प्रकार का नाम उम्मीद करते हैं, विशेष रूप से

Type t = Type.GetType("ClassB"); // results in t == null 
BaseClass c = Activator.CreateInstance(t) as BaseClass; // fails 

मैं इस काम के लिए एक ही वर्ग के नाम कॉन्फ़िगर करते समय कैसे मिल सकता है? पूर्ण नाम के नाम के लिए नामस्थान को नामस्थान से सम्बंधित करें? क्या कोई और प्रतिबिंब कॉल है जो काम करता है?

यदि आपको लगता है कि यह बेकार है और मुझे कॉन्फ़िगरेशन को पूर्ण प्रकार का नाम रखने की उम्मीद करनी चाहिए, तो मैं उस समाधान के लिए खुला हूं! बस मुझे मनाने के लिए तर्क प्रदान करें।

(मैं इस विधानसभा/नाम स्थान के बाहर से एक प्रकार लोड नहीं किया जाएगा)

+0

मैं सिर्फ आईओसी कंटेनर का उपयोग कर सकता हूं, लंबे नामों से निपट सकता हूं, और मेरे लिए ऑब्जेक्ट सृजन प्राप्त कर सकता हूं! –

उत्तर

6

के बाद से आप जानते हैं कि सभी वर्गों में एक ही नाम स्थान से आ रही हो जाएगा, यह एक बार कॉन्फ़िगर और उपयोग करते हैं:

<appConfig> 
    <SuperAppConfig handlerNamespace="BigCorp.SuperApp"> 
     <Handler class="ClassB" /> 
    </SuperAppConfig> 
</appConfig> 

संपादित करें: मैं नामवर्ग करने के लिए बदल बेहतर के अर्थ को निरूपित करने के वह विशेषता।

+0

मैं असेंबली लोडिंग के उत्तरों, कोड और चर्चा की सराहना करता हूं। लेकिन मुझे विन्यास पर फोकस के लिए ब्रायन का जवाब पसंद है (क्योंकि मैं पूर्ण प्रकार के नाम से दूर नहीं जा सकता)। –

18

या तो विधानसभा से योग्य-नाम का उपयोग, या सभा के काबू पाने और Assembly.GetType(name) का उपयोग करें। इस मामले में, जब से तुम कॉन्फ़िग फ़ाइल में प्रकार चाहते हैं, विधानसभा से योग्य जाने के लिए एक वैध तरीका है - लेकिन क्योंकि आप अपने सभी प्रकार जानते ही विधानसभा में हैं:

Assembly assembly = typeof(SomeKnownType).Assembly; // in the same assembly! 
Type type = assembly.GetType(name); // full name - i.e. with namespace (perhaps concatenate) 
object obj = Activator.CreateInstance(type); 

स्थिर Type.GetType(string) की जांच कर चुका है नियम जो अक्सर भ्रम पैदा करता है ... यह कॉलिंग असेंबली और कुछ सिस्टम असेंबली को देखता है - लेकिन सभी लोड असेंबली नहीं।

+0

मेरे पास एक सेवा संदर्भ है जिसे मैं इसका उपयोग करना चाहता हूं, लेकिन यह असेंबली की प्रकार सूची (कक्षा से बने) में दिखाई नहीं देगा। भले ही मैं कन्स्ट्रक्टर हार्डकोड को कॉल करके संदर्भ का एक वस्तु बना सकता हूं। – MrFox

5
(I will not be loading a type from outside this assembly/namespace)

उपर्युक्त रेखा के कारण, यह मानना ​​सुरक्षित है कि आप जानते हैं कि नामस्थान क्या है। आप की तरह कुछ भी नहीं किया जा सका: आप संभवतः भविष्य में लोड करने के लिए अतिरिक्त रणनीति वर्गों को जोड़ने के लिए, शायद एक अतिरिक्त विधानसभा के माध्यम से सक्षम होने की अपेक्षा तो

Type t = Type.GetType("Namespace." + className); 
BaseClass c = Activator.CreateInstance(t) as BaseClass; 

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

+0

यह वास्तव में निर्भर करता है कि वह कोड कहां है (और आप "बाहर से" कैसे व्याख्या करते हैं - यानी वह वर्ग है या कॉलर?)। एक असेंबली-योग्य नाम के बिना, Type.GetType (स्ट्रिंग) * केवल * वर्तमान असेंबली और कुछ सिस्टम असेंबली को देखेंगे। यह यादृच्छिक संदर्भित डीएलएस में प्रकार नहीं मिलेगा। –

2

मैं एप्लिकेशन कॉन्फ़िगरेशन में पूर्ण प्रकार के नाम के साथ जा रहा हूं।नीचे एक से थोड़ा अधिक पूर्ण, लेकिन अभी भी तुच्छ उदाहरण

<SuperAppConfig> 
    <ObjectConfig provider="BigCorp.SuperApp.ClassA"> 
     <add name="one" /> 
     <add name="two" /> 
    </ObjectConfig> 
</SuperAppConfig> 

और कारखाने वर्ग वास्तव में बनाता है वह यह है कि इस

private static Assembly a = typeof(IFactoryObject).Assembly; 
public static IFactoryObject CreateObject(String providerName) 
{ 
    Type t = a.GetType(providerName) 
    IFactoryObject o = Activator.CreateInstance(t) as IFactoryObject; 
    return o; 
} 
1
BaseClass c = Activator.CreateInstance(t) as BaseClass; // fails 

भी इस तथ्य से प्रभावित हो सकती है, कि CreateInstance एक उदाहरण वापस नहीं करता है ऑब्जेक्टहैंडल में लिपटे बेसक्लास के उदाहरण के बजाय बेस क्लास का।

UnWrap विधि का उपयोग करने के बाद अपने बेस क्लास में कास्ट करें।

संबंधित मुद्दे