คุณมีคำถามที่ดี อาจมีการแลกเปลี่ยนกับโซลูชันของคุณ คำตอบที่ดีที่สุดนั้นขึ้นอยู่กับสิ่งที่คุณหมายถึงโดยขึ้นอยู่กับแพลตฟอร์ม ตัวอย่างเช่นหากคุณกำลังเริ่มต้นกระบวนการเพื่อเริ่มแอปพลิเคชันภายนอกและคุณเพียงสลับไปมาระหว่างแอปพลิเคชั่นหนึ่งกับอีกแอปหนึ่งคุณอาจจัดการกับปัญหานั้นได้โดยไม่ยุ่งยากมากเกินไป หากคุณกำลังพูดถึง P / Invoke กับไลบรารี่เนทีฟคุณจะต้องทำสิ่งนั้นให้เสร็จ อย่างไรก็ตามหากคุณกำลังเชื่อมโยงกับไลบรารีที่มีอยู่บนแพลตฟอร์มเดียวเท่านั้นคุณอาจต้องใช้หลายแอสเซมบลี
แอพภายนอก
คุณอาจไม่จำเป็นต้องใช้#if
คำสั่งในสถานการณ์นี้ เพียงตั้งค่าอินเทอร์เฟซและมีการใช้งานหนึ่งรายการต่อแพลตฟอร์ม ใช้โรงงานเพื่อตรวจหาแพลตฟอร์มและจัดหาอินสแตนซ์ที่ถูกต้อง
ในบางกรณีมันเป็นเพียงไบนารีที่คอมไพล์สำหรับแพลตฟอร์มเฉพาะ แต่ชื่อของไฟล์เรียกทำงานและพารามิเตอร์ทั้งหมดจะถูกกำหนดเหมือนกัน ในกรณีนั้นมันเป็นเรื่องของการแก้ไขปฏิบัติการที่ถูกต้อง สำหรับแอปตัวแปลงเสียงจำนวนมากที่สามารถทำงานได้บน Windows และ Linux ฉันมีตัวเริ่มต้นแบบคงที่เพื่อแก้ไขชื่อไบนารี
public class AudioProcessor
{
private static readonly string AppName = "lame";
private static readonly string FullAppPath;
static AudioProcessor()
{
var platform = DetectPlatform();
var architecture = Detect64or32Bits();
FullAppPath = Path.combine(platform, architecture, AppName);
}
}
ไม่มีอะไรแฟนซีที่นี่ ชั้นเรียนเฒ่าดีเพียง
P / วิงวอน
P / Invoke ค่อนข้างหลอกลวง บรรทัดล่างคือคุณต้องแน่ใจว่าโหลดไลบรารี่เนทีฟเวอร์ชันที่ถูกต้อง ในหน้าต่างคุณจะ P / เรียกSetDllDirectory()
ใช้ แพลตฟอร์มที่ต่างกันอาจไม่ต้องการขั้นตอนนั้น ดังนั้นนี่คือสิ่งที่สามารถยุ่ง คุณอาจต้องใช้#if
คำสั่งเพื่อควบคุมการโทรที่จะใช้ในการควบคุมการแก้ไขเส้นทางห้องสมุดของคุณ - โดยเฉพาะถ้าคุณรวมไว้ในแพ็คเกจการแจกจ่ายของคุณ
การลิงก์ไปยังไลบรารีที่ขึ้นอยู่กับแพลตฟอร์มที่แตกต่างอย่างสิ้นเชิง
แนวทางการกำหนดเป้าหมายหลายโรงเรียนแบบเก่าอาจมีประโยชน์ที่นี่ อย่างไรก็ตามมันมาพร้อมกับความอัปลักษณ์มากมาย ในวันที่บางโครงการพยายามมีเป้าหมาย DLL Silverlight, WPF และ UAP ที่อาจเกิดขึ้นเหมือนกันคุณจะต้องรวบรวมแอปพลิเคชันหลายครั้งด้วยแท็กการรวบรวมที่แตกต่างกัน ความท้าทายของแต่ละแพลตฟอร์มข้างต้นคือแม้ว่าพวกเขาจะแบ่งปันแนวคิดเดียวกัน แต่แพลตฟอร์มนั้นมีความแตกต่างกันมากพอที่คุณต้องหลีกเลี่ยงความแตกต่างเหล่านั้น #if
นี่คือที่เราได้รับในนรกของ
วิธีนี้ยังต้องการการแก้ไข.csproj
ไฟล์ด้วยมือเพื่อจัดการการอ้างอิงที่ขึ้นกับแพลตฟอร์ม เนื่องจาก.csproj
ไฟล์ของคุณเป็นไฟล์ MSBuild จึงเป็นไปได้อย่างสิ้นเชิงที่จะทำในลักษณะที่รู้จักและคาดเดาได้
#if นรก
คุณสามารถเปิดและปิดส่วนของรหัสโดยใช้#if
คำสั่งเพื่อให้มีประสิทธิภาพในการจัดการความแตกต่างเล็กน้อยระหว่างแอปพลิเคชัน บนพื้นผิวมันดูเหมือนความคิดที่ดี ฉันยังใช้มันเป็นเครื่องมือในการเปิดและปิดการสร้างภาพกล่องขอบเขตเพื่อดีบักโค้ดการวาด
ปัญหาหมายเลข 1 #if
คือไม่มีรหัสใดที่ปิดใช้งานถูกประเมินโดยตัวแยกวิเคราะห์ คุณอาจมีข้อผิดพลาดทางไวยากรณ์แฝงหรือแย่กว่านั้นคือข้อผิดพลาดเชิงตรรกะที่รอให้คุณคอมไพล์ไลบรารีอีกครั้ง สิ่งนี้จะยิ่งเป็นปัญหากับรหัสการเปลี่ยนโครงสร้างอีกครั้ง บางสิ่งที่ง่ายพอ ๆ กับการเปลี่ยนชื่อเมธอดหรือการเปลี่ยนลำดับของพารามิเตอร์จะจัดการได้ตามปกติ แต่เนื่องจาก parser ไม่เคยประเมินสิ่งใดที่ถูกปิดโดย#if
คำสั่งคุณก็มีรหัสที่แตกหักซึ่งคุณจะไม่เห็นจนกว่าคุณจะคอมไพล์ใหม่
รหัสการดีบักทั้งหมดของฉันที่เขียนในลักษณะนั้นต้องถูกเขียนใหม่หลังจากชุดการรีแฟคเตอร์แตกออกมา ระหว่างการเขียนใหม่ฉันใช้คลาส config ทั่วโลกเพื่อเปิดและปิดคุณสมบัติเหล่านั้น นั่นทำให้การพิสูจน์เครื่องมือ refactor แต่โซลูชั่นดังกล่าวไม่ได้ช่วยเมื่อ API แตกต่างอย่างสิ้นเชิง
วิธีที่ฉันชอบ
วิธีการที่ฉันชอบตามบทเรียนที่เจ็บปวดจำนวนมากที่เรียนรู้และแม้กระทั่งจากตัวอย่างของ Microsoft ก็คือการใช้ชุดประกอบหลายชุด
แอสเซมบลี NetStandard หลักหนึ่งจะกำหนดอินเทอร์เฟซทั้งหมดและประกอบด้วยรหัสทั่วไปทั้งหมด การติดตั้งใช้งานแพลตฟอร์มจะอยู่ในชุดประกอบแยกต่างหากที่จะเพิ่มคุณสมบัติเมื่อรวมอยู่
วิธีการนี้ได้รับการยกตัวอย่างโดย API การกำหนดค่าใหม่และสถาปัตยกรรมเอกลักษณ์ในปัจจุบัน เมื่อคุณต้องการการรวมที่เฉพาะเจาะจงมากขึ้นคุณเพียงแค่เพิ่มการประกอบใหม่เหล่านั้น แอสเซมบลีเหล่านั้นยังมีฟังก์ชันส่วนขยายเพื่อรวมตัวเองเข้ากับการตั้งค่าของคุณ หากคุณใช้วิธีการฉีดแบบพึ่งพาวิธีส่วนขยายเหล่านั้นอนุญาตให้ไลบรารีลงทะเบียนบริการ
นี่เป็นวิธีเดียวที่ฉันรู้เพื่อหลีกเลี่ยง#if
นรกและตอบสนองสภาพแวดล้อมที่แตกต่างกันอย่างมีนัยสำคัญ