PDA

View Full Version : سوال: ایجاد یک کپی از یک شی بدون ارجاع



mohammad diba
شنبه 08 اسفند 1388, 16:59 عصر
سلام بر دوستان بزرگوار
من می خوام یک کپی از یک کنترل مثل پنل ایجاد کنم اما نمی خوام به هم اشاره کنند و می خوام کاملا مستقل باشند به نظر شما چه کار کنم؟؟؟؟؟؟؟؟؟

r00tkit
شنبه 08 اسفند 1388, 17:39 عصر
می شه کمی بیش تر توضیح بدی تا شاید بتونم کمک کنم

mehdi.mousavi
شنبه 08 اسفند 1388, 18:05 عصر
سلام بر دوستان بزرگوار من می خوام یک کپی از یک کنترل مثل پنل ایجاد کنم اما نمی خوام به هم اشاره کنند و می خوام کاملا مستقل باشند به نظر شما چه کار کنم؟؟؟؟؟؟؟؟؟

سلام.
چنین نیازی عموما یک "هشدار باش" برای طراحی ناصحیح یک سیستم نرم افزاری هستش. اگر از Office Automation Model استفاده کنید، (یا دیگر روشهای Modeling نرم افزار)، دیگه هرگز به چنین نیازهایی بر نمیخورید.

Panel چیه؟ یک Container که خودش میتونه حاوی N تا Container دیگه باشه. برای انجام این کار ناصحیح، دو روش به ذهنم میرسه. یکی اینکه یک Panel جدید new کنید و دونه به دونه کنترلهای توی Container اصلی رو پیمایش کنید و به Panel تازه new شده اضافه کنید. سپس کلیه Property ها و خصیصه های Panel اصلی رو هم به Panel جدید Assign کنید و این کار رو بطور Recursive برای کلیه Control های Contained شده ادامه بدید. (که بیشتر یک کابوس بنظر میرسه).

روش دوم استفاده از تکنیک Serialization/Deserialization هستش که اولین بار توی پروژه (هر چی سعی کردم یادم نیومد اسمش)، معرفی شد! در این روش، Graph Object بطور کلی Serialize میشه و سپس هنگام Deserialize شدن، یه Object جدیدی دارید که Deep Copy شده. من قبلا در این مورد در این پست (http://blog.mehdi.biz/2007/06/shallow-copy-vs-deep-copy.html) توضیح داده ام...

اما بازم بهتون توصیه میکنم اینکارو نکنید! این داره نشون میده که به احتمال زیاد طراحی شما ایراد داره که به چنین نیازی رسیده اید.

موفق باشید.

توسعه نویس
یک شنبه 02 مرداد 1390, 18:27 عصر
با سلام. موضوع این تایپیک بعد از 2 سال هنوز مشکل خیلی هاست. بنابر این با عرض پوزش که این رو بالا آوردم.

جناب آقای موسوی میتونید در مورد روشهای modeling نرم افزار توضیح بدید؟ یعنی کسانی که نیاز دارند که از یک آبجکت کپی تهیه کنند مشکل طراحی دارند؟

اگر من یک پنل با n تا آبجکت و کنترل درونش را کپی بگیرم تا در جای دیگری (RunTime) مورد استفاده قرار دهم، یعنی یک اشتباه تکنیکی در طراحی نرم افزارم کردم؟ پس در روشهای درست Modeling به جای این روش چه کار میکنند؟

با سپاس

gwbasic
یک شنبه 02 مرداد 1390, 19:19 عصر
شک نکنید که کپی یک قسمت از UI ایراد داره!!!
فرض کنید پنل شما حاوی کنترل هایی هست که می خواهید در همان فرم یا فرم دیگری ازش استفاده کنید ( که البته منطقی هست) ولی اطلاعاتی که این کنترلهای داخل پنل نشون می دن که تصدیق می کنید تکراری نیستند. خوب برای این کار کافیه یک UserControl تعریف کنید و به کرات ازش نمونه بسازید و در فرض نمایش بدی.د مزیت این کار اینه که تمام منطقی که لازم دارید می تونید یک جا و اونم در UserControl تعریف کنید و حتی قابلیت dataBinding رو هم بهش بدین!
بهتر نیست؟

توسعه نویس
دوشنبه 03 مرداد 1390, 09:59 صبح
در این موارد ساده، بله حق با شماست ولی در مواردی خاص مثل پروژه بنده چکار باید کرد؟ !!

من در یک پروژه کامپوننتی ساختم که یک فرم را از برنامه نویس دریافت میکند که حاوی پنلی خاص با کنترلهای چیده شده زیادی هست. و کامپوننت این فرم را دریافت کرده و پنل مورد نظر را استخراج کرده و برای برنامه خودش بکار می برد. در اینجا مسئله بنظر مشخص است. کامپوننت یک نمونه از فرم را میگیرد و پنل مورد نظر را شناسایی کرده و یک کپی از آن را میسازد. کاری که من کردم.

حالا اگر برنامه نویس یک UserControl را ساخته و به جای پنل به کامپوننت ارسال کند، چگونه کامپوننت باید تشخیص دهد که این یک یوزر کنترل هست و باید از آن یک نمونه جدید ساخت؟

gwbasic
دوشنبه 03 مرداد 1390, 10:49 صبح
فرم رو چطور ازبرنامه نویس دریافت می کنه؟ فرم ذخیره شده ، از روی فایل می خونه یا object فرم رو دارین اگه ذخیره شده که مسلمه باید Deserialize بشه
در مورد اینکه از کجا بفهمیم UserControl هست هم مشخصه ، تایپ اون object نشون می ده که هست اگه شما قرار reflect کنین از همون یکی دوباره می سازید

توسعه نویس
دوشنبه 03 مرداد 1390, 12:29 عصر
فرم بصورت عادی در پروژه Add میشود و بعد یک نمونه از آن بصورت پارامتر از نوع object به کامپوننت ارسال میشود:
Component.FormTemplate = new Form1();

بعد هم در کامپوننت که بصورت یک Dll در اختیار برنامه نویس هست به این صورت بازیافت میشود:
if (FormTemplate is Window) workPanel = (FormTemplate as Window).FindName("Content") as Panel;

حالا اگه به جای این کار برنامه نویس یک یوزر کنترل بسازه و به کامپوننت ارسال کنه، در کامپوننت چگونه باید از این یوزر کنترل نمونه جدید ساخت؟ میشه یک مثال ساده بزنید؟

gwbasic
دوشنبه 03 مرداد 1390, 14:00 عصر
هیچ فرقی نمی کنه ، یه userControl یه کلاس که از usercontrol ارث می بره مثلا MyCustomUserControl خوب نمونه گرفتن از این کلاس هم که شما بهتر از من بلدید کافیه new کنید مثل همه کنترل های دیگه می مونه دلیلی که شما متوجه نمی شید رو من نمی دونم
MyCustomUserControl رو به FormTemplate کامپوننتتون بدید بعد تو کامپوننتتون FormTemplate رو به MyCustomUserControl تبدیل cast کنید

Legend M.A.R
دوشنبه 03 مرداد 1390, 14:54 عصر
فرم بصورت عادی در پروژه Add میشود و بعد یک نمونه از آن بصورت پارامتر از نوع object به کامپوننت ارسال میشود:
Component.FormTemplate = new Form1();

بعد هم در کامپوننت که بصورت یک Dll در اختیار برنامه نویس هست به این صورت بازیافت میشود:
if (FormTemplate is Window) workPanel = (FormTemplate as Window).FindName("Content") as Panel;

حالا اگه به جای این کار برنامه نویس یک یوزر کنترل بسازه و به کامپوننت ارسال کنه، در کامپوننت چگونه باید از این یوزر کنترل نمونه جدید ساخت؟ میشه یک مثال ساده بزنید؟

امیدوارم بدردت بخوره

public class userObject : UserControl, ICloneable
{
private string text;
private Control p_parent;

public object Clone()
{
userObject g_new = new userObject();
g_new.text = this.text;
g_new.Parent = this.Parent;
//...
return g_new;
}

public string Text
{
get { return this.text; }
set { this.text = value; }
}

internal userObject()
{
}

public userObject(IContainer _Container)
{
//...
InitializeComponent();
//...
}
}

public class mainform : Form
{
private userObject myObject = new userObject();
private void changeText(userObject _Value)
{
_Value.Text = "New Value";
}

private void button1_Click(object sender, EventArgs e)
{
changeText((userObject)myObject.Clone());
}
}


در ضمن بعضی از کلاس ها (تا جایی که می دونم به غیر از Control ها) دارای Clone هستن

توسعه نویس
سه شنبه 04 مرداد 1390, 09:56 صبح
با تشکر از شما.
ولی بحث ما الان Clone کردن یک آبجکت نیست. بحث ما ساختن یک آبجکت جدید از یک Type میباشد.

قدیما تقریبا تا VS2005 آبجکت ها اکثرا دارای متد Clone بودند، ولی از اون به بعد این متد توسط ماکروسافت حذف شد. کلا الان منطق ماکروسافت اینو میگه که از یک آبجکت ساخته شده نباید کپی تهیه کرد. البته در این سالها برنامه نویسان توابع متنوع با روشهای مختلفی را برای حل این موضوع ارائه کردند، که تقریبا من همشون رو دیده و تست کردم. هر کدومشون معایب خاص خودشون رو دارند و اکثرا منجر به پایین اومدن Performance برنامه و همچنین اشغال شدید حافظه میشوند. یکی از راه ها همونیه که دوست من Legend M.A.R انجام دادید. البته برای من کارایی نداره چرا که UserControle احتمالی من کانتاینر هست و خودش حاوی بیش صد کنترل و پنل دیگر هستش. اما برای کلاسهایی که Property ها و المانهای مشخص شده و ساده تری دارند مناسب هست. من کلاسی دارم که یک UserControle را بصورت یک آبجکت ساخته شده از کاربر تحویل میگیرد و این یوزر کنترل توسط همون کاربر ساخته شده است و دارای کدهایی هست که اون ساخته و کلاس من هیچ اطلاعاتی از داخل اون نداره و حالا میخوام از اون UserControle نمونه های بیشمار جدید بسازه، در حالی که یک آبجکت بهش پاس داده شده، نه یک Type.

کد زیر رو نگاه کنید:
Button myButton = new Button();

در بالا myButton یک آبجکت هست و Button یک Type هست.

البته از اصل موضوع دور نشیم. (اون چطور منطقی در طراحی نرم افزار هستش که هیچ وقت نیاز به کپی کردن یک آبجکت نداشته باشیم؟).

gwbasic
سه شنبه 04 مرداد 1390, 12:18 عصر
توسعه نویس عزیز هر object ای تایپ داره می شه از typeof() یا .GetType() استفاده کرد و تایپش رو مشخص کرد.
در ضمن از هر تایپی که نمی دونیم چی هست می تونیم از کد با استفاده از کد زیر یک نمونه از اون ساخت

object instance = Activator.CreateInstance(sometype);


البته من فکر می کنم که شما فقط یک userControl خاص رو پاس می کنید که اگه چندتا هست خوب از کد بالا استفاده کنید
نکته ای که من رو واقعا گیج می کنه شما شی ای از usercontrol رو دارید خوب همون رو نمایش بدین دیگه چرا دوباره می خواین بسازین؟؟؟

توسعه نویس
سه شنبه 04 مرداد 1390, 16:36 عصر
از کدی که دادید ممنون. حتما تستش میکنم.

نکته ای که من رو واقعا گیج می کنه شما شی ای از usercontrol رو دارید خوب همون رو نمایش بدین دیگه چرا دوباره می خواین بسازین؟؟؟

این به منطق برنامه من برمیگرده. در برنامه من از این UserControle باید یک لیست آبجکت تهیه بشه و مقادیرش هم از دیتابیس متناظر درون اونها کپی بشه و بدین صورت یک لیست سفارشی ساخته شده مانند گریدویو ولی بسیار متفاوت تر خواهیم داشت. (این از اون مواردیه که آدم به فکر کپی از یک آیتم موجود میفته!)
البته برای این UserControl حتما یک اینترفیس میزارم که کاربر با ارث بری ازش ملزم به پیاده سازی متدهای اون باشه تا اینطوری استاندارد بشه.