PDA

View Full Version : چگونگی ایجاد شی جدید در زمان اجرای برنامه بر اساس یک رشته



vof.ir
چهارشنبه 25 مرداد 1391, 10:42 صبح
با سلام

عنوان تاپیک بدین صورت با سوال من مرتبط می شود.

من در برنامه ام می خواهم بخشی داشته باشم به اسم Favorites مثل چیزی که در مرورگر ها هست.
مثلا کاربر میبینه که با یک سری منو زیاد کار دارد؛ میاد اون ها را درگ می کنه داخل یک پنل که توی فرم اصلی قرار دارد.
خب مثلا فرض کنید برنامه که اجرا شده؛ کاربر میاد 6 تا منو را به این قسمت اضافه می کند.
برای اینکه دفعه بعدی هم این پنل همین آیتم های درگ داپ شده را نشان دهد باید اطلاعاتی را در جایی ذخیره کند. مثلا یک فایل xml حاوی اسم آیتم؛ و....

خب برای اینکه بتونیم در زمانی که اطلاعات آیتم ها از فایل متنی خوانده می شه؛ و بر اساس آن یک سری آیتم به آن پنل اضافه می شود؛ بر روی آن ها کلیک کنیم و فرم مرتبط با منوی مربوطه باز شود؛ چه کاری باید انجام داد؟
به نظر من اگر بشود نام فرمی که میخواهیم باز شود را به عنوان یک پراپرتی برای اون آیتم در نظر بگیریم و آن را در فایل متنی هم ذخیره کنید؛ و بر اساس نام فرمی که ذخیره کردیم ؛ از کلاس هم نام با آن فرم ؛ instance بسازیم؛ مشکل حل می شود.
منتهی الان سوالم این هست که اولا چه جوری میشه از روی یک رشته کلاس مرتط با آن را ساخت؟

یک سری مطلب در مورد Reflection خواندم!
دوستان منتظر نظر و پیشنهادات و انتقادات شما هستم
با تشکر!

the king
چهارشنبه 25 مرداد 1391, 21:35 عصر
این متدی که نوشتم ببینید :

private object CreateObject(string typeName)
{
System.Reflection.Assembly currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
Type type = currentAssembly.GetType(currentAssembly.GetName(). Name + "." + typeName);
if (type != null)
{
return type.GetConstructor(new Type[0]).Invoke(null);
}
System.Reflection.AssemblyName[] names = currentAssembly.GetReferencedAssemblies();
foreach (System.Reflection.AssemblyName name in names)
{
string qualifiedName = System.Reflection.Assembly.CreateQualifiedName(nam e.FullName, typeName);
type = Type.GetType(qualifiedName);
if (type != null)
{
return type.GetConstructor(new Type[0]).Invoke(null);
}
}
return null;
}

اسم یک Type رو که فرضا نام کلاس ئه دریاقت می کنه و شیء جدیدی از اون نوع می سازه و تحویل میده.
currentAssembly اون اسمبلی ای است که داره اجرا میشه، یعنی پروژه شما. اول چک می کنه ببینه اون typeName جزئی از بدنه
اون اسمبلی هست یا نه ، فرضا :

object f2 = CreateObject("Form2");
((Form)f2).Show();


اگر پیدایش نکرد، سراغ بقیه اسمبلی هایی میره که در پروژه ازشون استفاده شده. names لیست مشخصات اون اسمبلی ها است.
در هر کدوم شون سعی می کنه typeName رو پیدا کنه و شیء ای از اون نوع بسازه، فرضا :

object rnd = CreateObject("System.Random");
int i = ((Random)rnd).Next(100);
MessageBox.Show(i.ToString());


می توانید توسط typeName هر شیء ای که سازنده اش عمومی باشه و نیازی به پارامتر نداره بسازید. بعضی از کلاس ها سازنده عمومی ندارند
و بعضی هاشون سازنده ای که بدون پارامتر باشه ندارند، فرضا شما نمی توانید از System.IO.FileInfo شیء بسازید مگر اینکه پارامتر fileName اش
را مشخص کنید. البته در صورت تمایل می توانید CreateObject را طوری ویرایش کنید تا بتواند پارامتر یا پارامتر هایی را به سازنده ارسال کند.

vof.ir
پنج شنبه 26 مرداد 1391, 15:07 عصر
با سلام و خسته نباشید. خیلی خیلی ممنونم ا زشما دوست عزیز . توضیحات جامع و کاملی بود! اما یک نکته ای ببینید
من چیزی که می خواهم این هست که بشود بدون نیاز به CAST کردن به نوع فرم مورد نظر؛ آن را نمایش دهم . البته نمی دانم این امکان در سی شارپ و CLR اصلا وجود داره یا نه؟
یک جورایی می شود Dynamic Cast
به نظر شما می شود؟
این کدی که شما لطف کردید نوشتید؛ در نهایت امر باز هم نیاز به یک سوئیچ کیس دارد؛ مثلا بر مبنای اینکه مقدار موجود در Tag اون منو؛ چی هست؛ باید آبجکت برگشتی از اون متد را به نوع خاصی از فرم های مد نظرم Cast کنم.
درسته؟
باز هم ممنونم.