PDA

View Full Version : سوال در مورد xml serialization



youngold
دوشنبه 26 تیر 1391, 07:23 صبح
چرا كلاس System.Net.NetworkInformation.NetworkInterface و امثال اون
ايكس ام ال سريال نميشه؟ راهي نداره؟

uniqueboy_ara
دوشنبه 26 تیر 1391, 08:18 صبح
خوب چرا از این استفاده نمیکنی؟ System.XML.Serialization

youngold
دوشنبه 26 تیر 1391, 09:25 صبح
خوب چرا از این استفاده نمیکنی؟ System.XML.Serialization
حالت خوبه دوست عزيز؟ من ميگم با همين ايكس ام ال سريال ميكنم اين كلاس رو جواب نميده سريال متوقف ميشه شما نيم اسپيس ايكس ام ال سريال رو به من ميدي؟!

منظورم اينه كلاس System.Net.NetworkInformation.NetworkInterface رو با همين xmlSerializer دارم سريال ميكنم نميشه!

youngold
دوشنبه 26 تیر 1391, 09:45 صبح
اساتيد محترم لطفاً جواب بديد

tooraj_azizi_1035
دوشنبه 26 تیر 1391, 10:37 صبح
سلام
باید سعی کنی کلاسی از System.Net.NetworkInformation.NetworkInterface مشتق کنی و ویژگی Serializable رو به اون بدی بعد کلاس جدید رو Serialize کنی:



[Serializable()]
public class NewNetworkInterface:System.Net.NetworkInformation. NetworkInterface

youngold
دوشنبه 26 تیر 1391, 10:49 صبح
سلام
باید سعی کنی کلاسی از System.Net.NetworkInformation.NetworkInterface مشتق کنی و ویژگی Serializable رو به اون بدی بعد کلاس جدید رو Serialize کنی:



[Serializable()]
public class NewNetworkInterface:System.Net.NetworkInformation. NetworkInterface



جواب نميده كلاً تو سينتكس خطا هاي مربوط به آبستركت كلاس و ... ميده

youngold
دوشنبه 26 تیر 1391, 11:20 صبح
يعني راهي براي ايكس ام ال سريال كردن فيلد هاي اين كلاس ها نيست؟!

tooraj_azizi_1035
دوشنبه 26 تیر 1391, 15:43 عصر
شما اجازه مشتق کردن یک کلاس جدید از یک کلاس abstract رو دارید.

مستقیماً نمیشه از روی NetworkInterface نمونه سازی کرد باید GetAllNetworkInterfaces (http://msdn.microsoft.com/en-us/library/system.net.networkinformation.networkinterface.get allnetworkinterfaces.aspx) رو فراخوانی بکنی که یک آرایه بهت برمی گردونه.


بهترین کار:


using (var stream = File.Create("file.xml"))
{
var serializer = new XmlSerializer(typeof(NetworkInterface[]));
serializer.Serialize(stream, NetworkInterface.GetAllNetworkInterfaces());
}


نمونه کد GetAllNetworkInterfaces (http://msdn.microsoft.com/en-us/library/system.net.networkinformation.networkinterface.get allnetworkinterfaces.aspx)


public static void ShowNetworkInterfaces()
{
IPGlobalProperties computerProperties = IPGlobalProperties.GetIPGlobalProperties();
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
Console.WriteLine("Interface information for {0}.{1} ",
computerProperties.HostName, computerProperties.DomainName);
if (nics == null || nics.Length < 1)
{
Console.WriteLine(" No network interfaces found.");
return;
}
Console.WriteLine(" Number of interfaces .................... : {0}", nics.Length);
foreach (NetworkInterface adapter in nics)
{
IPInterfaceProperties properties = adapter.GetIPProperties();
Console.WriteLine();
Console.WriteLine(adapter.Description);
Console.WriteLine(String.Empty.PadLeft(adapter.Des cription.Length,'='));
Console.WriteLine(" Interface type .......................... : {0}", adapter.NetworkInterfaceType);
Console.WriteLine(" Physical Address ........................ : {0}",
adapter.GetPhysicalAddress().ToString());
Console.WriteLine(" Operational status ...................... : {0}",
adapter.OperationalStatus);
string versions ="";
// Create a display string for the supported IP versions.
if (adapter.Supports(NetworkInterfaceComponent.IPv4))
{
versions = "IPv4";
}
if (adapter.Supports(NetworkInterfaceComponent.IPv6))
{
if (versions.Length > 0)
{
versions += " ";
}
versions += "IPv6";
}
Console.WriteLine(" IP version .............................. : {0}", versions);
ShowIPAddresses(properties);
// The following information is not useful for loopback adapters.
if (adapter.NetworkInterfaceType == NetworkInterfaceType.Loopback)
{
continue;
}
Console.WriteLine(" DNS suffix .............................. : {0}",
properties.DnsSuffix);
string label;
if (adapter.Supports(NetworkInterfaceComponent.IPv4))
{
IPv4InterfaceProperties ipv4 = properties.GetIPv4Properties();
Console.WriteLine(" MTU...................................... : {0}", ipv4.Mtu);
if (ipv4.UsesWins)
{
IPAddressCollection winsServers = properties.WinsServersAddresses;
if (winsServers.Count > 0)
{
label = " WINS Servers ............................ :";
ShowIPAddresses(label, winsServers);
}
}
}
Console.WriteLine(" DNS enabled ............................. : {0}",
properties.IsDnsEnabled);
Console.WriteLine(" Dynamically configured DNS .............. : {0}",
properties.IsDynamicDnsEnabled);
Console.WriteLine(" Receive Only ............................ : {0}",
adapter.IsReceiveOnly);
Console.WriteLine(" Multicast ............................... : {0}",
adapter.SupportsMulticast);
ShowInterfaceStatistics(adapter);
Console.WriteLine();
}

Saeed_m_Farid
دوشنبه 26 تیر 1391, 16:36 عصر
يعني راهي براي ايكس ام ال سريال كردن فيلد هاي اين كلاس ها نيست؟!
نه متاسفانه! شما نمی‌تونید در یک کلاس abstract از XmlSerializer استفاده کنید؛ شاید بخاطر امنیت، یا توسعه‌پذیری و ... از الگوی طراحی Abstract Pattern (http://csharpdesignpatterns.codeplex.com/wikipage?title=Abstract%20Factory%20Pattern) برای NetworkInterface (http://msdn.microsoft.com/en-us/library/system.net.networkinformation.networkinterface.asp x) استفاده شده و اگه نگاه کنید، از سازنده (constructor) تو این کلاس خبری نیست و فقط یه متد استاتیک گذاشتن که درحقیقت همون اینترفیس رو برمی‌گردونه! به هرصورت برای استفاده از XmlSerializer کلاس شما باید یک سازنده public داشته باشه و همچنین فقط اعضاء public سریال میشن، یعنی هرچیزی که برای اشیاء خارج کلاس دیده بشه تو serialize میاد...
______________
بگذریم، راه حل که به ذهن من میرسه، استفاده از Linq to XML هست؛ مثلاً به اینصورت:
private void saveNICs()
{
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
/* Below commented code doesn't work! :"(
* Because The XmlSerializer only works on publicly accessible types and members;
* If you look at the NetworkInterface class it is abstract...
XmlSerializer xmlFormat = new XmlSerializer(typeof(NetworkInterface[]));
FileStream fStream =
new FileStream("NICData.xml",
FileMode.Create,
FileAccess.Write,
FileShare.None);
xmlFormat.Serialize(fStream, nics);
fStream.Close();
*/
if (nics != null || nics.Length > 0)
{
XElement all = new XElement("AllNetworkInterfaces");
foreach (NetworkInterface adapter in nics)
{
XElement nic =
new XElement(adapter.ToString(),
new XElement("ID", adapter.Id),
new XElement("Description", adapter.Description),
new XElement("NetworkInterfaceType", adapter.NetworkInterfaceType),
new XElement("PhysicalAddress", adapter.GetPhysicalAddress().ToString()),
new XElement("OperationalStatus", adapter.OperationalStatus));
all.Add(nic);
}
all.Save("NICData.xml");
}
}

که البته شما می‌تونید هر مشخصاتی از Network Interface هاتون که مایل بودین رو در المنت‌های XML اضافه کنید، اینا به ذهن من میرسید، فقط همین‌ها رو برای نمونه گذاشتم؛ ضمناً کامنت‌ها رو برای این گذاشتم که نوع استفاده از XmlSerializer برای دوستانی که آشنا نیستن، مشخص بشه و خلاصه دلیل عدم اجراش هم قبل کد کامنت‌شده نوشتم...


شما اجازه مشتق کردن یک کلاس جدید از یک کلاس abstract رو دارید.

مستقیماً نمیشه از روی NetworkInterface نمونه سازی کرد باید GetAllNetworkInterfaces (http://msdn.microsoft.com/en-us/library/system.net.networkinformation.networkinterface.get allnetworkinterfaces.aspx) رو فراخوانی بکنی که یک آرایه بهت برمی گردونه.

بهترین کار:


using (var stream = File.Create("file.xml"))
{
var serializer = new XmlSerializer(typeof(NetworkInterface[]));
serializer.Serialize(stream, NetworkInterface.GetAllNetworkInterfaces());
}


اجازۀ مشتق شدن داره ولی نمی‌شه از چنین کلاس‌هایی برای XmlSerializer استفاده کرد، درصورت استفاده از این کد خطای "System.InvalidOperationException (http://msdn.microsoft.com/en-us/library/system.invalidoperationexception.aspx)" میده که دلیلش رو بالا گفتم...

موفق باشید./

youngold
دوشنبه 26 تیر 1391, 17:15 عصر
نه متاسفانه! شما نمی‌تونید در یک کلاس abstract از XmlSerializer استفاده کنید؛ شاید بخاطر امنیت، یا توسعه‌پذیری و ... از الگوی طراحی Abstract Pattern (http://csharpdesignpatterns.codeplex.com/wikipage?title=Abstract%20Factory%20Pattern) برای NetworkInterface (http://msdn.microsoft.com/en-us/library/system.net.networkinformation.networkinterface.asp x) استفاده شده و اگه نگاه کنید، از سازنده (constructor) تو این کلاس خبری نیست و فقط یه متد استاتیک گذاشتن که درحقیقت همون اینترفیس رو برمی‌گردونه! به هرصورت برای استفاده از XmlSerializer کلاس شما باید یک سازنده public داشته باشه و همچنین فقط اعضاء public سریال میشن، یعنی هرچیزی که برای اشیاء خارج کلاس دیده بشه تو serialize میاد...
______________
بگذریم، راه حل که به ذهن من میرسه، استفاده از Linq to XML هست؛ مثلاً به اینصورت:
private void saveNICs()
{
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
/* Below commented code doesn't work! :"(
* Because The XmlSerializer only works on publicly accessible types and members;
* If you look at the NetworkInterface class it is abstract...
XmlSerializer xmlFormat = new XmlSerializer(typeof(NetworkInterface[]));
FileStream fStream =
new FileStream("NICData.xml",
FileMode.Create,
FileAccess.Write,
FileShare.None);
xmlFormat.Serialize(fStream, nics);
fStream.Close();
*/
if (nics != null || nics.Length > 0)
{
XElement all = new XElement("AllNetworkInterfaces");
foreach (NetworkInterface adapter in nics)
{
XElement nic =
new XElement(adapter.ToString(),
new XElement("ID", adapter.Id),
new XElement("Description", adapter.Description),
new XElement("NetworkInterfaceType", adapter.NetworkInterfaceType),
new XElement("PhysicalAddress", adapter.GetPhysicalAddress().ToString()),
new XElement("OperationalStatus", adapter.OperationalStatus));
all.Add(nic);
}
all.Save("NICData.xml");
}
}

که البته شما می‌تونید هر مشخصاتی از Network Interface هاتون که مایل بودین رو در المنت‌های XML اضافه کنید، اینا به ذهن من میرسید، فقط همین‌ها رو برای نمونه گذاشتم؛ ضمناً کامنت‌ها رو برای این گذاشتم که نوع استفاده از XmlSerializer برای دوستانی که آشنا نیستن، مشخص بشه و خلاصه دلیل عدم اجراش هم قبل کد کامنت‌شده نوشتم...


اجازۀ مشتق شدن داره ولی نمی‌شه از چنین کلاس‌هایی برای XmlSerializer استفاده کرد، درصورت استفاده از این کد خطای "System.InvalidOperationException (http://msdn.microsoft.com/en-us/library/system.invalidoperationexception.aspx)" میده که دلیلش رو بالا گفتم...

موفق باشید./


مرسي از جوابت، اما وارد كردن فيلد ها به صورت دستي به ايكس ام ال به ذهن خودمم ميرسيد اما راهي ميخواستم كه زحمت اين كارو براي بسياري از كلاس ها نداشته باشيم اينطور كه مفهوم سريال كردن عوض ميشه، به هر حال ممنون.

youngold
دوشنبه 26 تیر 1391, 17:22 عصر
به نظرتون با System.reflection بيرون كشيدن فيلد ها به ترتيب امكان داره؟ يا راهي كه ليست فيلد ها رو به ترتيب از كلاس بگيريم؟

youngold
دوشنبه 26 تیر 1391, 17:48 عصر
يك راه براي ايكس ام ال كردن اين كلاس ها با محتواشون پيدا كردم درچند مستقيم نيست اما منطقي تر از اين راه حل هاست!
يكي از اساتيد كه علاقه به حل اين موضوع كه مشكل خيلي از برنامه نويسان هست داره زحمت يك پيام خصوصي رو بكشه بعد نتيجه رو در تاپيك اعلام ميكنيم

جواب سوال بالا رو هم بديد ، ممنون

Saeed_m_Farid
دوشنبه 26 تیر 1391, 18:25 عصر
مرسي از جوابت، اما وارد كردن فيلد ها به صورت دستي به ايكس ام ال به ذهن خودمم ميرسيد اما راهي ميخواستم كه زحمت اين كارو براي بسياري از كلاس ها نداشته باشيم اينطور كه مفهوم سريال كردن عوض ميشه، به هر حال ممنون.
بله، من اولش عرض کردم که : "نه متاسفانه! شما نمی‌تونید در یک کلاس abstract از XmlSerializer استفاده کنید"
این یک راه فرعی بود که به ذهن من رسید، بازم میگم: شما فقط برای کلاسهایی که دارای ساختار عمومی هستند می‌تونید از مفهوم سریال کردن استفاده کنید! مگه اینکه کل کلاس NetworkInterface رو با [Serializable] پیاده‌سازی کنید که مطمئناً خیلی کارتون بیشتر از راهی خواهد بود که من عرض کردم؛ باید تمام اعضاء abstract رو implement کنید و ...
در مورد سوال بالایی هم بیشتر توضیح بدین، من که متوجه ارتباط System.Reflection با مشکل شما نشدم؛ ضمناً یکم در مورد "منطقي تر" هم بیشتر توضیح بدین! فکر می‌کنید دات نت پشت زمینه وقتی serialize‌ میکنه، چه عملیاتی انجام میده؟!

youngold
دوشنبه 26 تیر 1391, 21:15 عصر
در مورد سوال بالایی هم بیشتر توضیح بدین، من که متوجه ارتباط System.Reflection با مشکل شما نشدم؛ ضمناً یکم در مورد "منطقي تر" هم بیشتر توضیح بدین! فکر می‌کنید دات نت پشت زمینه وقتی serialize‌ میکنه، چه عملیاتی انجام میده؟!

منظورم برگردوندن فيلد ها بود، اون منطقي تر هم منظور استفاده از ساخت ايكس اي ام ال از روي كلاس و ساختار و محتواش با workflow بود اما يك سري مشكل هست مثل اينكه ساختار ايكس اي ام ال كه از كلاس ميگيريم نيم اسپيس اپليكشن و اسمبلي نيم توش ذخيره ميشه و فقط توي همون اپليكشن ديسريال ميشه و ... كه اين موضوع اگه حل بشه ... بگذريم، فكر خاصي بايد در رابطه با پشت پرده سريال شدن بكنم؟!
پشت زمينه دات نت تا جايي كه من ميدونم با استفاده از بازتاب فيلد ها اون ها رو به ترتيب ليست ميكنه و در ايكس ام ال وارد ميكنه تا لازم نباشه اينجوري دستي بريزيم فيلد هارو تو ايكس ام ال!

Saeed_m_Farid
دوشنبه 26 تیر 1391, 22:08 عصر
منظورم برگردوندن فيلد ها بود
اون منطقي تر هم منظور استفاده از ساخت ايكس اي ام ال از روي كلاس و ساختار و محتواش با workflow بود اما يك سري مشكل هست مثل اينكه ساختار ايكس اي ام ال كه از كلاس ميگيريم نيم اسپيس اپليكشن و اسمبلي نيم توش ذخيره ميشه و فقط توي همون اپليكشن ديسريال ميشه و ... كه اين موضوع اگه حل بشه ... بگذريم،
فكر خاصي بايد در رابطه با پشت پرده سريال شدن بكنم؟!
پشت زمينه دات نت تا جايي كه من ميدونم با استفاده از بازتاب فيلد ها اون ها رو به ترتيب ليست ميكنه و در ايكس ام ال وارد ميكنه تا لازم نباشه اينجوري دستي بريزيم فيلد هارو تو ايكس ام ال!



اگه دات نت می‌خواست اجازه بده شما اون فیلدها رو برگردونید، abstract تعریف‌شون نمی‌کرد.
ساخت زَمل(XAML) ربطی به این‌کار نداره! اون برای خودش یک شیوۀ برنامه‌نویسی! هست که با WPF پیوند خورده ولی می‌تونید مستقیماً برای کارهای دیگه‌ای ازش استفاده کنید که فکر نمی‌کنم بشه ارتباطی بین اون با مشکل شما پیدا کرد؛ شما نه WorkFlow دارید، نه Window و نه هیچ چیز دیگه‌ای که به attribute های Xaml مربوط باشه؛ این ایده فقط کار شما رو غیرمنطقی‌تر می‌کنه.
نه فکر خاصی که نه! ولی وقتی می‌گید غیرمنطقی، باید بدونید که اگه XmlSerializer خوب بود، لازم نمی‌شد Linq to XML ایجاد بشه؛ استفاده از XmlSerializer حداقل 4 مرحله زمان‌گیر و مستعد بروز خطا به برنامه‌شما تحمیل می‌کنه، که در ادامه توضیح میدم...
هزینۀ "تا لازم نباشه اينجوري دستي بريزيم فيلد هارو تو ايكس ام ال!" ؛ این میشه که:



بازاء هربار فراخوانی XmlSerializer یک جفت XmlSerializationReader و XmlSerializationWriter برای آنالیز بقول شما "بازتاب فيلدها" ایجاد بشه!
ممکنه برنامه شما حق دسترسی (!Full permissions) به پوشۀ پروفایل temp کاربر برنامه در ویندوز رو نداشته باشه!(+ (http://stackoverflow.com/questions/542312/asp-net-access-to-the-temp-directory-is-denied))
هزینه سنگین تولید اسمبلی‌ها به ازاء هر نوع (Type) بکار رفته در object ای که شما بهش پاس می‌دین، به برنامه تحمیل بشه!
بازاء هر اسمبلی فایل‌های موقتی #C تولید و کامپایل شده و اجباراً به پروسس شما بچسبه!
و ... همۀ اینها فقط بخاطر اینکه کمی کدنویسی راحت‌تر بشه، ولی هیچکدوم از این مراحل بی‌معنی در Linq to XML طی نمی‌شه و حالا شما خودتون قضاوت کنید، استفاده از کدوم غیرمنطقی‌تر هست؟



+http://barnamenevis.org/images/misc/quote_icon.png (http://www.careerride.com/Csharp-how-does-XmlSerializer-work.aspx)
a. The XmlSerializer constructor generates a pair of classes derived from XmlSerializationReader and XmlSerializationWriter by analysis of the classes using reflection
b. Temporary C#‎‎‎‎‎‎‎‎‎‎‎‎‎ files are created and compiled into a temporary assembly and then loaded into a process
c. The XmlSerializer caches the temporary assemblies on a per-type basis as the code generated like this is expensive. This cached assembly is used after a class is created
d. Therefore the XmlSerialize requires full permissions on the temporary directory which is a user profile temp directory for windows applications

youngold
دوشنبه 26 تیر 1391, 22:54 عصر
همه اين موارد براي همه پروژه ها مهم نيستن اما آيا xml serialization براي همه سريال كردن ها "ممکنه برنامه شما حق دسترسی (!Full permissions) به پوشۀ پروفایل temp کاربر برنامه در ویندوز رو نداشته باشه!" شامل اين مورد ميشه؟ اگر ميشه ميشه سطح دسترسي داد؟ ، پروژه اي هست كه بايد بدونم كه اگه اينطوره اصلاً از xml serial استفاده نكنم.
به طور كلي نظر شما براي استفاده از ايكس ام ال سريال تو پروژه هايي كه توي سيستم هاي مختلف و فراواني قراره اجرا بشه چيه؟ سطح خطا هاش ارزششو نداره؟ حداقل منظورم براي سريال كردن يك كلاس ساده و بدون ذخيره اون در فايل ايكس ام ال هست

Saeed_m_Farid
سه شنبه 27 تیر 1391, 09:42 صبح
زیاد ربطی به "سيستم هاي مختلف و فراوان" نداره! اگه بخوام دسته‌بندی کاربردی بکنم، اینطوری میشه گفت:


XML serialization: معمولاً جاهایی که شما می‌خواین کل یک Object رو (با آخرین state) بردارید و عین همون رو جای دیگه استفاده کنید از XML serialization استفاده می‌کنید و اینکار اکثراً در روال‌های راه دور (Remote) مثل وب سرویس‌ها، WCF و Net remoting. و ... مورد استفاده داره که شما نیازی به دونستن محتویات و کوئری گرفتن ازش و ... ندارین و بازم معمولاً این Object از کلاسی هست که اجازۀ سریال کردن میده، نه اینترفیس‌ها یا کلاس‌های abstract یا sealed و ... دات‌نت؛ چون شما مدیریتی روی نحوۀ تعریف کلاس ندارید و مشکلاتی که ذکر کردین، از مهمترین اونهاست؛ شما هیچ کنترلی روی اینکه چه چیزی باید تو serialization بیاد یا نه ندارید! موردِ کاربردش، معمولاً جاهایی هست که دوطرف فرستنده / گیرنده، پلت فرم دات نت هست، مثل لایه‌ها / کانال‌های WCF (م. DataContract (http://msdn.microsoft.com/en-us/library/ms733127.aspx))
LINQ to XML: برای مواردی که شما نیاز به داده‌های کنترل شده، ساختار اختصاصی خودتون برای XML، نیاز به پیمایش داده‌ها و ... دارید و خلاصه اینکه وقتی می‌خواین بدونید دقیقاً چه داده‌هایی ردوبدل میشه و روشون کنترل داشته باشید و انعطاف‌پذیری لازم هست (اکثر موارد)؛ بی‌شک LINQ to XML گزینۀ بهتری هست! چون داده‌های بیخود رد و بدل نمیشه، شما می‌دونید چه اتفاقی میافته، ریسورس الکی هدر نمیشه، دست‌تون تو پیمایش داده‌ها باز هست و ...

برای مقایسه فرض کنید دارید Visual Studio نصب می‌کنید؛ وقتی دکمه Customize می‌زنید، انگار از LINQ to XML استفاده کردین و وقتی Default میذارین ویزارد همه کار رو خودش انجام بده (Magic!) و تمام موارد (آفیس، ++C و Dotfuscator و ...) هم باهاش نصب میشن، یعنی کاری شبیه XML serialization کردین...