PDA

View Full Version : سوال: حذف و آپدیت یک خط از فایل متنی



vb8334
دوشنبه 13 آبان 1392, 22:40 عصر
سلام

دوستان من دارم یه کدی می نویسم که توی یه فایل متنی یه خط رو که با توجه به انتخاب کاربر اون خط
رو تو فایل پاک میکنه و آپدیت می کنه من با پاک کردن مشکلی ندارم مشکل من با آپدیت کردنه.
من کد رو اینجا پیوست میکنم یه نگاهی بندازید ممنون میشم

ببینید توی فایل هم یه اسامی هستند که داری (id , name , family , age , country) مشخصه ها هستند.
حالا کاربر میاد رو دکمه find کلیک میکنه تو تکست باکس مثلآ عدد 1 رو میزنه شخصی که شناسه شماره
1 رو داره میاره. حالا کاربر میاد اسم شخص مثلآ بوده رضا رو تغییر میده به سارا حالا باید این خط فایل جایگزین اسم رضا بشه.



مرسی

drstrike
سه شنبه 14 آبان 1392, 11:03 صبح
سلام
مشکل اپدیت تو لایه DataAccess بود. بعد از حذف مشتری قدیم، مشتری جدید رو اضافه نمی کنید!
public void Update(Customer customer)
{
List<string> lines = new List<string>();
var customerStr = File.ReadAllLines(@"data\customers.dat");

foreach (var s in customerStr)
{
lines.Add(s);
var objCustomer = customerSerializer.Deserialize(s);
if (objCustomer.Id == customer.Id)
{
lines.Remove(s);

// بعد از حذف مشتری جدید رو باید اضافه کنید که آپدیت شه
lines.Add(customerSerializer.Serialize(customer));
}
File.WriteAllLines(@"data\customers.dat", lines);
}
}

البته متد serialize هم یه مشکل کوچیک داشت که رفع شد:
public string Serialize(Customer customer)
{
var result = string.Empty;
foreach (var propertyInfo in customer.GetType().GetProperties().Where(p => !p.PropertyType.IsGenericType))
{
result += propertyInfo.GetValue(customer, null) + ",";
}

return result.Remove(result.Count() - 1);
}

متدهارو میشه بهینه تر هم نوشت که I/O رو کمتر درگیر کنه.

واقعا خوشحال شدم یک مثال اینجا دیدم که از معماری چندلایه استفاده کرده. اسم لابه WindowsClient هم به UI یا Presentation تغییر بده.

موفق باشی

vb8334
سه شنبه 14 آبان 1392, 13:27 عصر
در ضمن من نمی خوام از تکنیک linq استفاده کنم برای متد serialize .

vb8334
سه شنبه 14 آبان 1392, 14:11 عصر
من متد serialize رو به این صورت نوشتم ولی با کد حال نکردم چون یه قسمت رو hardcode کردم قسمت حلقه for منظورم هستش

اگه این کار رو نمی کردم این ارور رو می گرفتم Index was outside the bounds of the array حالا راه بهتری هستش برای این کار که hardcode نکنم و این ارور که نوشتم رو بهم نده.

public string Serialize(Customer customer)
{
string[] data = new string[5];
for (int i = 1; i <= 2 - 1; i++)
{
data[0] = customer.Id.ToString();
data[1] = customer.FirstName;
data[2] = customer.LastName;
data[3] = customer.Age.ToString();
data[4] = customer.Country;
}
var customerString = string.Join(",", data);
return customerString;
}

drstrike
سه شنبه 14 آبان 1392, 17:10 عصر
بهترین کار استفاده از Reflection هست (همان روشی که تو پست قبلی گذاشتم)؛ چون اگر در آینده Propertyهای دیگه ای هم به موجودیت تون اضافه کنید باز هم متد Serialize بدون تغییر بدرستی کار می کنه.

اگر از LINQ نمی خواهید استفاده کنید متد رو به این شکل تغییر بدید:

public string Serialize(Customer customer)
{
var result = string.Empty;
foreach (var propertyInfo in customer.GetType().GetProperties())
{
if (!propertyInfo.PropertyType.IsGenericType)
{
result += propertyInfo.GetValue(customer, null) + ",";
}
}

return result.Remove(result.Count() - 1);
}

vb8334
سه شنبه 14 آبان 1392, 18:05 عصر
میشه یه توضیحی در مورد کدتون بدید
1) customer.GetType().GetProperties()
2)!propertyInfo.PropertyType.IsGenericType

یه توضیح کلی هم بدید ممنون میشم

vb8334
سه شنبه 14 آبان 1392, 21:02 عصر
من این کد رو برای متد loadAll نوشتم . اما یه ایرادی که داره اینکه هر بار آخرین مقدار رو نگه میداره یعنی کل مقداری که توی فایل رو نمیاره و فقط آخری رو میاره؟

public ICollection<Customer> LoadAll()
{
var alldata = File.ReadAllLines(address);

List<Customer> lst = new List<Customer>();

foreach (var s in alldata)
{
var objCustomer = customerSerializer.Deserialize(s);
lst.Add(objCustomer);
}

return lst;
}

drstrike
چهارشنبه 15 آبان 1392, 12:28 عصر
میشه یه توضیحی در مورد کدتون بدید
1) customer.GetType().GetProperties()
2)!propertyInfo.PropertyType.IsGenericType

یه توضیح کلی هم بدید ممنون میشم

با استفاده از Reflection به اعضای یک کلاس، struct و... میشه دسترسی داشته باشید.فقط کافیه اسم اون Member رو داشته باشید.
برا استفاده از Reflection باید یک Type داشته باشید. Type هم به دو روش میشه بدست آورد:

1) typeof(Customer) // نام کلاس مربوطه

2) var customer = new Customer();
customer.GetType(); // استفاده از متد GetType یک نمونه از کلاس مربوطه
حالا با استفاده از Type بدست آمده می تونید به اعضای کلاس دسترسی پیدا کنید، مثلا Propertyها، فلیدها، متدها...
که توی متد Serialize، اول همه ی Propertyها رو بدست آوردیم و بررسی کردیم که اگر نوع داده ش جنریک نبود مقدار رو بگیره به یک رشته اضافه کن. و در آخر کامای اضافه رو پاک می کنیم.

اینطوری هر چندتا Property داشتی باشید، مقدارشون با متد GetValue گرفته میشه و به رشته اضافه میشه.


من این کد رو برای متد loadAll نوشتم . اما یه ایرادی که داره اینکه هر بار آخرین مقدار رو نگه میداره یعنی کل مقداری که توی فایل رو نمیاره و فقط آخری رو میاره؟

توی کلاس CustomerSerialize یک فلید تعریف کردید که صرفا تو متد Deserialize استفاده میشه! و هر سری که یک رشته رو Deserialize میکنید مقدار ایتم های اضافه شده قبلی رو هم تغییر میده! (چون reference Type هست).

متد Deserialize رو به این شکل تغییر بدید:
public Customer Deserialize(string str)
{
var customer = new Customer();
var strCustomer = str.Split(',');

customer.Id = int.Parse(strCustomer[0]);
customer.FirstName = strCustomer[1];
customer.LastName = strCustomer[2];
customer.Age = int.Parse(strCustomer[3]);
customer.Country = strCustomer[4];

return customer;
}