รูปแบบการออกแบบสำหรับการนำเข้าข้อมูลของแหล่งข้อมูลประเภทต่าง ๆ และไปยังประเภทปลายทางต่างๆ


14

ฉันต้องออกแบบและสร้างสคริปต์นำเข้า (ใน C #) ที่สามารถจัดการต่อไปนี้:

  • อ่านข้อมูลจากแหล่งต่าง ๆ (XML, XSLX, CSV)
  • ตรวจสอบข้อมูล
  • เขียนข้อมูลไปยังวัตถุประเภทต่าง ๆ (ลูกค้าที่อยู่)

ข้อมูลจะมาจากแหล่งที่มาจำนวนหนึ่ง แต่แหล่งที่มาจะมีรูปแบบการนำเข้าหนึ่งรูปแบบเสมอ (เช่น csv, xml, xslx) รูปแบบการนำเข้าอาจแตกต่างกันไปตามแหล่งที่มา รูปแบบการนำเข้าใหม่อาจถูกเพิ่มในอนาคต ประเภทวัตถุปลายทางจะเหมือนกันเสมอ (ลูกค้าที่อยู่และอื่น ๆ )

ฉันกำลังคิดเกี่ยวกับการใช้ยาชื่อสามัญและฉันอ่านบางอย่างเกี่ยวกับรูปแบบของโรงงาน แต่ฉันเป็น noob ที่ค่อนข้างใหญ่ในพื้นที่นี้

รูปแบบการออกแบบที่เหมาะสมในการแก้ไขปัญหานี้คืออะไร


ง่าย ๆ เข้าไว้.
NoChance

คำตอบ:


11

คุณกำลังจะไปกับแนวคิดที่แฟนซีมากเกินไปเร็วเกินไป ยาสามัญ - เมื่อคุณเห็นกรณีใช้พวกเขา แต่อย่างอื่นไม่ต้องกังวล รูปแบบของโรงงาน - มีความยืดหยุ่นมากเกินไป (และเพิ่มความสับสน) สำหรับสิ่งนี้

ง่าย ๆ เข้าไว้. ใช้การปฏิบัติขั้นพื้นฐาน

  1. ลองนึกภาพสิ่งทั่วไประหว่างทำการอ่านสำหรับ XML สิ่งที่อ่านสำหรับ CSV สิ่งที่ต้องการบันทึกต่อไปบรรทัดถัดไป เนื่องจากอาจมีการเพิ่มรูปแบบใหม่ลองนึกภาพความธรรมดาที่รูปแบบที่กำหนดจะมีกับรูปแบบที่รู้จัก ใช้ commonality นี้และกำหนด 'ส่วนต่อประสาน' หรือสัญญาที่ทุกรูปแบบจะต้องปฏิบัติตาม แม้ว่าพวกเขาจะยึดติดกับพื้นดินทั่วไป แต่พวกเขาทั้งหมดอาจมีกฎภายในเฉพาะของพวกเขา

  2. สำหรับการตรวจสอบความถูกต้องของข้อมูลให้ลองใส่วิธีการเสียบบล็อกรหัสตัวตรวจสอบความถูกต้องใหม่หรือแตกต่างกันได้อย่างง่ายดาย ดังนั้นอีกครั้งให้ลองกำหนดอินเทอร์เฟซที่ตัวตรวจสอบความถูกต้องแต่ละตัวซึ่งรับผิดชอบการสร้างข้อมูลชนิดใดชนิดหนึ่งโดยเฉพาะปฏิบัติตามสัญญา

  3. สำหรับการสร้างโครงสร้างข้อมูลคุณอาจถูก จำกัด โดยผู้ออกแบบวัตถุผลลัพธ์ที่แนะนำมากกว่าสิ่งใด ลองคิดดูว่าขั้นตอนต่อไปของวัตถุข้อมูลคืออะไรและมีการปรับแต่งใด ๆ ที่คุณสามารถทำได้โดยการรู้ว่าการใช้งานครั้งสุดท้ายเป็นอย่างไร ตัวอย่างเช่นหากคุณรู้ว่าจะใช้วัตถุในแอปพลิเคชันแบบโต้ตอบคุณสามารถช่วยผู้พัฒนาแอพนั้นโดยการให้ 'การสรุป' หรือจำนวนวัตถุหรือข้อมูลประเภทอื่น ๆ

ฉันจะบอกว่าส่วนใหญ่เป็นรูปแบบเทมเพลตหรือรูปแบบกลยุทธ์ โครงการทั้งหมดจะเป็นรูปแบบอะแดปเตอร์


+1 โดยเฉพาะอย่างยิ่งสำหรับย่อหน้าแรก (และเป็นเรื่องดีที่เห็นว่าคุณได้ข้อสรุปเช่นเดียวกับฉันในย่อหน้าสุดท้าย)
Doc Brown

โปรดระลึกถึงสถาปัตยกรรมของโครงการทั้งหมดเพื่อปรับรูปแบบหนึ่งให้เป็นรูปแบบอื่น คุณสามารถจินตนาการถึงสถานการณ์ใด ๆ ที่ใครบางคนอาจใช้เพียงส่วนเดียวในโครงการอื่นได้หรือไม่? EG อาจมีตัวตรวจสอบความถูกต้องของข้อมูลใหม่ออกมาในตลาดและทำงานได้กับเซิร์ฟเวอร์ SQL เท่านั้น ดังนั้นตอนนี้คุณแค่ต้องการให้ ot อ่าน XML ที่กำหนดเองและใส่ในเซิร์ฟเวอร์ SQL โดยข้ามขั้นตอนที่เหลือ
Andyz Smith

เพื่ออำนวยความสะดวกนี้ไม่เพียง แต่ชิ้นส่วนที่ควรจะมีการทำสัญญาภายในของพวกเขาว่าพวกเขาเป็นไปตามควรจะมีชุดของสัญญาที่กำหนดปฏิสัมพันธ์ระหว่างชิ้น
Andyz Smith

@AndyzSmith - ฉันมีปัญหาเหมือนกันในรหัสของฉัน ฉันเข้าใจทุกอย่างเกี่ยวกับรหัสของคุณยกเว้นรูปแบบของการ์ดเชื่อมต่อ เมื่อคุณบอกว่าโครงการทั้งหมดเป็นตัวอย่างของรูปแบบของอะแดปเตอร์คุณสามารถอธิบายได้หรือไม่
gansub

9

สิ่งที่เห็นได้ชัดคือการใช้รูปแบบกลยุทธ์ มีชั้นฐานทั่วไปReadStrategyและสำหรับรูปแบบการป้อนข้อมูลแต่ละประเภทรองเช่นXmlReadStrategy, CSVReadStrategyฯลฯ ซึ่งจะช่วยให้คุณสามารถเปลี่ยนการนำเข้าการประมวลผลเป็นอิสระจากการประมวลผลและยืนยันผ่านระบบการประมวลผลการส่งออก

ขึ้นอยู่กับรายละเอียดอาจเป็นไปได้ที่จะเก็บส่วนใหญ่ของการนำเข้าทั่วไปและแลกเปลี่ยนเฉพาะบางส่วนของการประมวลผลอินพุต (ตัวอย่างเช่นการอ่านบันทึกหนึ่งรายการ) นี้อาจนำคุณไปสู่รูปแบบวิธีการแม่แบบ


หมายความว่าเมื่อใช้รูปแบบกลยุทธ์ฉันต้องสร้างวิธีแยกต่างหากสำหรับการแปลงวัตถุ (ลูกค้าที่อยู่) จากต้นทางไปยังปลายทาง สิ่งที่ฉันต้องการจะทำคืออ่านแปลงและตรวจสอบแต่ละวัตถุและวางไว้ในรายการเพื่อให้สามารถบันทึกรายการในฐานข้อมูลในภายหลัง
jao

@ เจ้า: ถ้าคุณอ่านคำตอบของฉันอีกครั้งคุณจะเห็นว่าคำแนะนำของฉันคือการสร้าง "ReadStrategy" ไม่ใช่ "ConvertStrategy" ดังนั้นคุณจะต้องเขียนวิธีการต่าง ๆ สำหรับการอ่านวัตถุ (หรือส่วนเพิ่มเติมใด ๆ ของกระบวนการของคุณเป็นส่วนบุคคลสำหรับรูปแบบไฟล์เฉพาะ)
หมอบราวน์

7

รูปแบบที่เหมาะสมสำหรับยูทิลิตี้การนำเข้าที่คุณอาจต้องการขยายในอนาคตคือใช้ MEF - คุณสามารถใช้หน่วยความจำต่ำโดยโหลดตัวแปลงที่คุณต้องการได้ทันทีจากรายการที่ขี้เกียจสร้าง MEF ที่นำเข้าที่ตกแต่งด้วยคุณสมบัติ ที่ช่วยเลือกตัวแปลงที่ถูกต้องสำหรับการนำเข้าที่คุณกำลังพยายามดำเนินการและให้วิธีการแยกคลาสการนำเข้าที่แตกต่างออกไปได้อย่างง่ายดาย

MEF แต่ละส่วนสามารถสร้างขึ้นเพื่อสนองต่อการนำเข้าอินเทอร์เฟซด้วยวิธีมาตรฐานบางอย่างที่แปลงแถวของไฟล์นำเข้าเป็นข้อมูลเอาต์พุตของคุณหรือแทนที่คลาสพื้นฐานด้วยฟังก์ชันการทำงานพื้นฐาน

MEF เป็นเฟรมเวิร์กสำหรับการสร้างสถาปัตยกรรมปลั๊กอิน - วิธีสร้าง outlook และ Visual Studio, ส่วนขยายที่น่ารักเหล่านั้นทั้งหมดใน VS เป็นส่วน MEF

ในการสร้างแอป MEF (Managed Extensability Framework) ให้เริ่มด้วยการรวมการอ้างอิง System.ComponentModel.Composition

กำหนดอินเตอร์เฟสเพื่อระบุสิ่งที่ตัวแปลงจะทำ

public interface IImportConverter
{
    int UserId { set; }        
    bool Validate(byte[] fileData, string fileName, ImportType importType);
    ImportResult ImportData(byte[] fileData, string fileName, ImportType importType);
}

สามารถใช้กับไฟล์ทุกประเภทที่คุณต้องการนำเข้า

เพิ่มแอททริบิวไปยังคลาสใหม่ที่กำหนดว่าคลาสใดจะ "ส่งออก"

[Export(typeof(IImportConverter))]
[MyImport(ImportType.Address, ImportFileType.CSV, "4eca4a5f-74e0")]
public class ImportCSVFormat1 : ImportCSV, IImportConverter
{
 ...interface methods...
}

สิ่งนี้จะกำหนดคลาสที่จะนำเข้าไฟล์ CSV (ในรูปแบบเฉพาะ: Format1) และมีแอตทริบิวต์ที่กำหนดเองซึ่งตั้งค่า MEF Export Attribute Metadata คุณจะทำสิ่งนี้ซ้ำสำหรับแต่ละรูปแบบหรือประเภทไฟล์ที่คุณต้องการนำเข้า คุณสามารถตั้งค่าแอตทริบิวต์ที่กำหนดเองด้วยคลาสเช่น:

[MetadataAttribute]
[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
public class ImportAttribute : ExportAttribute
{
    public ImportAttribute(ImportType importType, ImportFileType fileType, string customerUID)
        : base(typeof(IImportConverter))
    {
        ImportType = importType;
        FileType = fileType;
        CustomerUID = customerUID;
    }

    public ImportType ImportType { get; set; }
    public ImportFileType FileType { get; set; }
    public string CustomerUID { get; set; }
}

ในการใช้ตัวแปลง MEF คุณต้องนำเข้าชิ้นส่วน MEF ที่คุณสร้างขึ้นเมื่อรันโค้ดการแปลงของคุณ:

[ImportMany(AllowRecomposition = true)]
protected internal Lazy<IImportConverter, IImportMetadata>[] converters { get; set; }
AggregateCatalog catalog = new AggregateCatalog();

catalog รวบรวมชิ้นส่วนจากโฟลเดอร์ค่าเริ่มต้นคือที่ตั้งแอพ

converters เป็นรายการที่ขี้เกียจของชิ้นส่วน MEF ที่นำเข้า

จากนั้นเมื่อคุณรู้ว่าไฟล์ประเภทใดที่คุณต้องการแปลง ( importFileTypeและimportType) รับตัวแปลงจากรายการชิ้นส่วนที่นำเข้ามาconverters

var tmpConverter = (from x in converters
                    where x.Metadata.FileType == importFileType
                    && x.Metadata.ImportType == importType 
                    && (x.Metadata.CustomerUID == import.ImportDataCustomer.CustomerUID)
                    select x).OrderByDescending(x => x.Metadata.CustomerUID).FirstOrDefault();

if (tmpConverter != null)
{
     var converter = (IImportConverter)tmpConverter.Value;
     result = converter.ImportData(import.ImportDataFile, import.ImportDataFileName, importType);
....
}

การโทรไป converter.ImportDataใช้จะใช้รหัสในคลาสที่นำเข้า

อาจดูเหมือนโค้ดจำนวนมากและอาจต้องใช้เวลาสักครู่เพื่อให้หัวของคุณเกิดอะไรขึ้น แต่มันมีความยืดหยุ่นอย่างยิ่งเมื่อมันมาถึงการเพิ่มตัวแปลงชนิดใหม่


ฉันไม่เคยได้ยิน MEF มาก่อน มันคืออะไร?
เจ้า

2
@jao ตรวจสอบลิงก์สำหรับคำอธิบายแบบเต็ม เพิ่มตัวอย่าง MEF บางอย่างลงในคำตอบของฉัน
แมตต์

1
นี่เป็นวิธีที่ยอดเยี่ยมในการเริ่มเข้าสู่ MEF +1
paqogomez

MEF เป็นเทคโนโลยีไม่ใช่รูปแบบการออกแบบ ไม่-1จากฉันในขณะที่แนวคิดพื้นฐานยังคงสมเหตุสมผลและอาศัยรูปแบบกลยุทธ์ที่ควบคุมโดยIImportConverterอินเทอร์เฟซ
GETah

0

รูปแบบการออกแบบที่เหมาะสมในการแก้ไขปัญหานี้คืออะไร

C # idioms เกี่ยวข้องกับการใช้เฟรมเวิร์กต่อเนื่องในตัวเพื่อทำสิ่งนี้ คุณใส่คำอธิบายประกอบออบเจกต์ด้วยเมทาดาทาแล้วยกตัวอย่างซีเรียลไลเซอร์ต่าง ๆ ที่ใช้คำอธิบายประกอบเหล่านั้นเพื่อคัดลอกข้อมูลเพื่อใส่ลงในแบบฟอร์มที่ถูกต้องหรือในทางกลับกัน

รูปแบบ Xml, JSON และไบนารีเป็นเรื่องธรรมดามากที่สุด แต่ฉันจะไม่แปลกใจถ้าคนอื่นมีอยู่แล้วในรูปแบบแพคเกจที่ดีสำหรับคุณที่จะบริโภค


วิธีนี้ใช้ได้ดีถ้าคุณมีอิสระในการใช้รูปแบบไฟล์ของคุณเอง แต่ฉันคิดว่าวิธีการนี้จะล้มเหลวสำหรับรูปแบบที่ซับซ้อนที่กำหนดไว้ล่วงหน้าเช่น XSLX ซึ่งหมายถึงไฟล์ MS Excel ในรูปแบบ XML ที่บีบอัด
Doc Brown

ฉันสามารถแมปไฟล์ Excel กับวัตถุ แต่ฉันต้องการคัดลอกและปรับวิธีการดังกล่าวกับตัวอ่าน XML และ CSV และฉันต้องการที่จะให้รหัสสะอาดเท่าที่เป็นไปได้ ...
เจ้า

@docBrown - ยังไง? ตามหลักการแล้วการเปลี่ยนวัตถุให้เป็นชุดของเซลล์ใน Excel นั้นไม่แตกต่างจากการเปลี่ยนให้เป็นเอกสาร xml
Telastyn

@Telastyn: คุณบอกว่าคุณสามารถใช้เฟรมเวิร์กต่อเนื่องของ. NET Framework ในการอ่านรูปแบบ XLSX ได้หรือไม่ หากเป็นเช่นนั้นไลบรารีเช่น Open XML SDK หรือ NPOI จะล้าสมัย
Doc Brown

@docbrown: คำขอโทษของฉันคุณถูกต้อง - ฉันลืมไปว่าไม่มีคลาสเบสพื้นฐานของอนุกรมเนื่องจากมันเป็นหนึ่งในสิ่งแรกที่ทำในรหัสฐานข้อมูลใด ๆ ที่ฉันทำงานมา
Telastyn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.