PDA

View Full Version : سوال: مشکل در متد Deserialize برنامه؟



vb8334
دوشنبه 20 آبان 1392, 19:55 عصر
سلام

دوستان من برنامه ای نوشتم برای کار با فایل اما در کلاس Serializer یک متدی داریم بنام Deserialize
که ارور دریافت می کنم

Object of type 'System.String' cannot be converted to type 'System.Int32'.

من کد رو قرار میدم به همراه خود برنامه


public T Deserialize<T>(string entity)
{
var obj = Activator.CreateInstance<T>();
var stringProps = entity.Split(',');
var objProps = obj.GetType().GetProperties();

var propIndex = 0;

for (int i = 0; i < stringProps.Length; i++)
{
if (objProps[propIndex].PropertyType.FullName == "System.String")
{
objProps[propIndex].SetValue(obj, stringProps[i], null);
}
else if (objProps[propIndex].PropertyType.FullName == "System.Int32")
{
objProps[propIndex].SetValue(obj, stringProps[i], null);
}
else if (objProps[propIndex].PropertyType.FullName == "System.DateTime")
{
var cultureInfo = new CultureInfo("fa-IR");
DateTime dateTime = Convert.ToDateTime(stringProps[i], cultureInfo);
objProps[propIndex].SetValue(obj, stringProps[i], null);
}
else
{
i--;
}
propIndex++;
}
return obj;
}





مرسی

drstrike
پنج شنبه 23 آبان 1392, 14:02 عصر
سلام

متغیر strProps یک مجموعه از رشته هارو نگهداری می کنه و اعداد و تاریخ و... هم در این مجموعه بصورت رشته ذخیره می شوند.
وشما گفتید اگه نوع داده پراپرتی int بود، رشته "1" رو داخلش بریز!
else if (objProps[propIndex].PropertyType.FullName == "System.Int32")
{
objProps[propIndex].SetValue(obj, stringProps[i], null);
}

از رشته ها برای تشخیص نوع داده استفاده نکنید؛ ممکنه به هردلیلی "System.Int32" رو "System.Itn32" بنویسید که دیباگ کردن این کدها خیلی سخت هست. با typeof یا متد GetType براحتی می تونید این کار رو انجام بدید.

متد Deserialize جنریک هست و هر Entity می تونه اون رو فراخوانی کنه؛ پس رشته رو به این سادگی بهش پاس ندید!
بعنوان مثال، فرض کنید [objProps[propIndex به پراپرتی Age اشاره می کنه و [stringProps[i هم به مقدار Id، اینطوری میشه Age = 1 !

نکته بعدی اینکه Entityهای پروژه Inteface رو پیاده سازی می کنند؛ پس بهتر متد Deserialize رو به این اینترفیس محدود کنید:
public T Deserialize<T>(string entity) where T : ICommonEntity

اینطوری فقط کلاس هایی که این اینترفیس رو پیاده سازی کردند می تونند از این متد استفاده کنند.

اما Refactor کردن این متد:
اگر ترتیب تعریف پراپرتی ها با ترتیب ذخیره اطلاعات یکی است (یعنی در Entiy، اول Id بعد FirstName بعد LastName بعد... تعریف شده اند و اطلاعات هم اول Id بعد FirsName بعد LastNAme بعد... ذخیره می شود)، متد رو به این شکل تغییر دهید:
public T Deserialize<T>(string entity)
{
var obj = Activator.CreateInstance<T>();
var stringProps = entity.Split(',');
var objProps = obj.GetType().GetProperties().Where(p => !p.PropertyType.IsGenericType).ToList();

for (int i = 0; i < stringProps.Count(); i++)
{
objProps[i].SetValue(obj, stringProps[i], null);
}
}


روش دوم:
بجای ارسال پارامتر رشته به متد Deserialize، یک Dictionary یا HashTable به متد ارسال کنید که کلیدها نام پراپرتی و Valueها مقدار set شده در پراپرتی رو نگه داری کنند:
public T Deserialize<T>(IDictionary<string, object> propertiesDictionary, string entity)
{
var obj = Activator.CreateInstance<T>();
foreach (var property in propertiesDictionary)
{
obj.GetType().GetProperty(property.Key).SetValue(o bj, property.Value, null);
}

return obj;
}

ضمنا در مورد نحوه بازتولید خطا هم یکم بیشتر توضیح بدید؛ اینکه تو کدوم لایه،تو کدوم فایل،تو کدوم متد،چه داده ایی وارد کردید که خطا رخ داده و... بیشتر توضیح بدید که دوستان سریعتر جواب بدند

موفق باشید