मुझे ऐसे लोगों के लिए कुछ सुझाव मिले हैं, जो कहते हैं कि TypeDescriptionProvider
जुआन कार्लोस डियाज़ काम नहीं कर रहे हैं और न ही सशर्त संकलन पसंद करते हैं:
सबसे पहले, आपको फॉर्म कोड डिज़ाइनर में काम करने के लिए विज़ुअल स्टूडियो को फिर से शुरू करना पड़ सकता है (मुझे करना था, सरल पुनर्निर्माण काम नहीं किया - या हर बार नहीं)।
मैं सार आधार फॉर्म के मामले के लिए इस समस्या का समाधान प्रस्तुत करूंगा। मान लें कि आपके पास एक BaseForm
वर्ग है और आप चाहते हैं कि इस पर आधारित कोई भी प्रपत्र डिजाइन योग्य हो (यह होगा Form1
)। TypeDescriptionProvider
के रूप में जुआन कार्लोस डियाज़ द्वारा प्रस्तुत भी मेरे लिए काम नहीं किया। यहां बताया गया है कि मैंने इसे कैसे काम किया, इसे मिडलक्लास समाधान (स्मेलच द्वारा) के साथ जोड़कर, लेकिन सशर्त संकलन के बिना#if DEBUG
और कुछ सुधारों के साथ:
[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider<BaseForm, BaseFormMiddle2>))] // BaseFormMiddle2 explained below
public abstract class BaseForm : Form
{
public BaseForm()
{
InitializeComponent();
}
public abstract void SomeAbstractMethod();
}
public class Form1 : BaseForm // Form1 is the form to be designed. As you see it's clean and you do NOTHING special here (only the the normal abstract method(s) implementation!). The developer of such form(s) doesn't have to know anything about the abstract base form problem. He just writes his form as usual.
{
public Form1()
{
InitializeComponent();
}
public override void SomeAbstractMethod()
{
// implementation of BaseForm's abstract method
}
}
BaseForm वर्ग पर विशेषता को देखें। फिर आपको बस TypeDescriptionProvider
और दो मध्यम वर्गों की घोषणा करनी है , लेकिन चिंता न करें, वे फॉर्म 1 के डेवलपर के लिए अदृश्य और अप्रासंगिक हैं । पहला एक अमूर्त सदस्यों को लागू करता है (और बेस क्लास को गैर सार बनाता है)। दूसरा एक खाली है - यह काम करने के लिए वीएस फॉर्म डिजाइनर के लिए आवश्यक है। तब आप दूसरी मध्यम वर्ग को असाइन करते TypeDescriptionProvider
हैं BaseForm
। कोई सशर्त संकलन नहीं।
मुझे दो और समस्याएं हो रही थीं:
- समस्या 1: डिजाइनर (या कुछ कोड) में फॉर्म 1 को बदलने के बाद यह फिर से त्रुटि दे रहा था (जब इसे फिर से डिजाइनर में खोलने की कोशिश कर रहा है)।
- समस्या 2: बेसफ़ॉर्म के नियंत्रणों को गलत तरीके से रखा गया था जब फॉर्म 1 के आकार को डिजाइनर में बदल दिया गया था और फॉर्म को बंद कर दिया गया था और फॉर्म डिजाइनर में फिर से खोल दिया गया था।
पहली समस्या (आपके पास यह नहीं हो सकती है क्योंकि यह ऐसा कुछ है जो मुझे अपनी परियोजना में कुछ अन्य स्थानों पर परेशान करता है और आमतौर पर "एक्स टाइप करने के लिए एक्स टाइप नहीं कर सकता" अपवाद पैदा करता है)। मैं में इसे हल TypeDescriptionProvider
द्वारा प्रकार के नाम की तुलना (FullName) के बजाय प्रकार की तुलना में (देखें नीचे)।
दूसरी समस्या। मुझे वास्तव में नहीं पता है कि फॉर्म 1 क्लास में बेस फॉर्म के नियंत्रण क्यों नहीं हैं और आकार बदलने के बाद उनकी स्थिति खो गई है, लेकिन मैंने इसे काम किया है (अच्छा समाधान नहीं - यदि आप कोई बेहतर जानते हैं, तो कृपया लिखें)। मैं बस बेसफार्म के बटन (जो कि नीचे-दाएं कोने में होना चाहिए) को बेसफोर्म के लोड इवेंट से असिंक्रोनसली तरीके से मंगवाए गए सही तरीके से ले जाता हूं: BeginInvoke(new Action(CorrectLayout));
मेरे बेस क्लास में केवल "ओके" और "कैंसल" बटन होते हैं, इसलिए मामला सरल है।
class BaseFormMiddle1 : BaseForm
{
protected BaseFormMiddle1()
{
}
public override void SomeAbstractMethod()
{
throw new NotImplementedException(); // this method will never be called in design mode anyway
}
}
class BaseFormMiddle2 : BaseFormMiddle1 // empty class, just to make the VS designer working
{
}
और यहाँ आपके पास थोड़ा संशोधित संस्करण है TypeDescriptionProvider
:
public class AbstractControlDescriptionProvider<TAbstract, TBase> : TypeDescriptionProvider
{
public AbstractControlDescriptionProvider()
: base(TypeDescriptor.GetProvider(typeof(TAbstract)))
{
}
public override Type GetReflectionType(Type objectType, object instance)
{
if (objectType.FullName == typeof(TAbstract).FullName) // corrected condition here (original condition was incorrectly giving false in my case sometimes)
return typeof(TBase);
return base.GetReflectionType(objectType, instance);
}
public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
{
if (objectType.FullName == typeof(TAbstract).FullName) // corrected condition here (original condition was incorrectly giving false in my case sometimes)
objectType = typeof(TBase);
return base.CreateInstance(provider, objectType, argTypes, args);
}
}
और बस!
आपको अपने BaseForm के आधार पर रूपों के भविष्य के डेवलपर्स के लिए कुछ भी समझाने की ज़रूरत नहीं है और उन्हें अपने फ़ॉर्म को डिज़ाइन करने के लिए कोई चाल करने की ज़रूरत नहीं है! मुझे लगता है कि यह सबसे साफ समाधान हो सकता है (नियंत्रण को छोड़कर)।
एक और टिप:
यदि किसी कारण से डिज़ाइनर अभी भी आपके लिए काम करने से इनकार करता है, तो आप हमेशा कोड फ़ाइल में (या ) public class Form1 : BaseForm
को बदलने , वीएस फॉर्म डिजाइनर में इसे संपादित करने और फिर इसे फिर से बदलने की सरल चाल कर सकते हैं । मैं सशर्त संकलन पर इस चाल को पसंद करता हूं क्योंकि यह गलत संस्करण को भूलने और जारी करने की संभावना कम है ।public class Form1 : BaseFormMiddle1
BaseFormMiddle2