قضايا البومة والعالم: ربط مجموعتين بمساحات أسماء متطابقة وأسماء فئات


الليلة ، بدأ gelas محادثة حول كيفية عمل مديري الحزم على منصات مختلفة. خلال المحادثة ، جئنا إلى مناقشة الوضع عندما تحتاج إلى ربط مكتبتين بمشروع .NET Core الذي يحتوي على فئات تحمل نفس الاسم في نفس مساحة الاسم. نظرًا لأنني أقوم بعمل القليل جدًا من .NET Core ، فقد أردت التحقق من كيفية حل هذه المشكلة. ما جاء في هذا موصوف أكثر


تنويه . هل تحدث مثل هذه المواقف بشكل متكرر؟ لأكثر من 10 سنوات من العمل مع .NET ، لم يكن عليّ أبدًا التعامل مع موقف مماثل في مشروع حقيقي. لكن التجربة كانت مثيرة للاهتمام.


فقط تحسبًا ، سأوضح أنني سأجري التجربة باستخدام:


  • macOS 10.13 ،
  • .NET Core SDK 2.1.302
  • رايدر 2018.2

لذا ، سنقوم بمحاكاة موقف عندما حصلنا على مكتبتين تحتويان على الفئات التي نحتاجها والتي يجب أن نستخدمها في مشروعنا. في الوقت نفسه ، لا يمكننا الوصول إلى شفرة المصدر ، ولكن لا يمكننا فك التجميعات من أجل تغيير مساحات الأسماء فيها ، ومن ثم لا يمكننا الترجمة مرة أخرى.


إعداد التجربة


وهكذا ، بالنسبة للمبتدئين ، قم بإعداد بومة واحدة واثنين من الكرات الأرضية. كبومة ، سيكون لدينا مشروع يستهدف netcoreapp2.1. سننشئ مشروعين كروية ، أحدهما سيكون مستهدفًا أيضًا على netcoreapp2.1 ، والثاني على netstandard2.0



في كل مشروع ، نضع فئة Globe ، والتي ستكون في مساحات أسماء متطابقة ، ولكن سيكون لها تطبيقات مختلفة:


الملف الأول:


using System; namespace Space { public class Globe { public string GetColor() => "Green"; } } 

الملف الثاني:


 using System; namespace Space { public class Globe { public string GetColor() => "Blue"; } } 

المحاولة الأولى


نظرًا لأنه ، وفقًا لظروف المشكلة ، يجب أن نعمل مع التجمعات الخارجية ، وليس المشاريع ، سنضيف روابط للمشروع وفقًا لذلك ، كما لو كانت مجرد مكتبات. للقيام بذلك ، قم أولاً بتجميع جميع المشاريع بحيث يكون لدينا Globe1.dll و Globe2.dll الذي نحتاجه. ثم أضف روابط لهم في المشروع على النحو التالي:



حاول الآن إنشاء متغير فئة Globe:



كما ترون ، تحذرنا IDE بالفعل في هذه المرحلة من وجود مشكلة في فهم المكان الذي يجب أن نأخذ منه فئة غلوب.


في البداية ، يبدو أن الوضع نموذجي تمامًا ويجب أن يكون هناك بالفعل الجاهزة ، المصبوب في الجرانيت ، الإجابة على Stack Overflow. كما اتضح ، لم يتم اقتراح أي حل لهذه المشكلة حتى الآن لـ .NET Core. أو جوجل لي تخذلني. لكنني تمكنت من العثور على شيء مفيد في Stack Overflow ، وكان المنشور الوحيد المعقول الذي تمكنت من الوصول إليه هو google عام 2006 ووصفت موقفًا مشابهًا للإصدار الكلاسيكي من .NET. في هذه الحالة ، تمت مناقشة مشكلة مشابهة جدًا في مستودع مشروع NuGet .


حتى الآن ، ليس هناك الكثير من المعلومات المفيدة ، لكنها لا تزال موجودة:



يبقى فهم كيفية القيام بذلك في .NET Core.


لسوء الحظ ، فإن النسخة الحالية من الوثائق تتحدث بشكل متواضع حول إمكانيات ربط الحزم / الرسوم الخارجية. كما أن وصف ملف csproj لا يلقي بأي شكل من الأشكال الضوء على إمكانية إنشاء أسماء مستعارة. ومع ذلك ، من خلال التجربة والخطأ ، تمكنت من معرفة أن الأسماء المستعارة للتجميعات في .NET Core لا تزال مدعومة. وهي مصنوعة على النحو التالي:


 <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.1</TargetFramework> </PropertyGroup> <ItemGroup> <Reference Include="Globe1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"> <HintPath>..\Globe1\bin\Debug\netcoreapp2.1\Globe1.dll</HintPath> <Aliases>Lib1</Aliases> </Reference> <Reference Include="Globe2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"> <HintPath>..\Globe2\bin\Debug\netstandard2.0\Globe2.dll</HintPath> <Aliases>Lib2</Aliases> </Reference> </ItemGroup> </Project> 

الآن يبقى تعلم كيفية استخدام هذه الأسماء المستعارة. ستساعدنا الكلمة الرئيسية الخارجية المذكورة سابقًا في ما يلي:


ما يلي مكتوب في الوثائق حوله:


في بعض الحالات ، قد تحتاج إلى الرجوع إلى نسختين من التجميعات بنفس أسماء الأنواع المؤهلة بالكامل. على سبيل المثال ، تحتاج إلى استخدام نسختين أو أكثر من التجميع في تطبيق واحد. باستخدام اسم مستعار خارجي للتجميع ، يمكنك تضمين مساحات أسماء لكل تجميع في مجمّع داخل مساحات أسماء مستوى الجذر المسماة بهذا الاسم المستعار ، مما يسمح لك باستخدامها في ملف واحد.
...
يقدم كل تعريف لاسم مستعار خارجي مساحة اسم إضافية على مستوى الجذر تتطابق مع مساحة الاسم العامة (ولكنها ليست بداخلها). وبالتالي ، يمكن إنشاء مراجع لأنواع من كل تجميع بدون غموض باستخدام اسمها الكامل ، جذرها هو الاسم المستعار المقابل لمساحة الاسم.

الحقيقة هنا هي عدم نسيان استخدام extern أيضًا في C # لإعلان طريقة مع تنفيذ خارجي من التعليمات البرمجية غير المُدارة. في هذه الحالة ، يتم استخدام extern عادةً مع سمة DllImport. يمكنك قراءة المزيد عن هذا في القسم المقابل من الوثائق .


لذا ، دعنا نحاول استخدام الأسماء المستعارة لدينا:


 extern alias Lib1; extern alias Lib2; using System; namespace Owl { ... public class SuperOwl { private Lib1::Space.Globe _firstGlobe; private Lib2::Space.Globe _secondGlobe; public void IntegrateGlobe(Lib1::Space.Globe globe) => _firstGlobe = globe; public void IntegrateGlobe(Lib2::Space.Globe globe) => _secondGlobe = globe; ... } } 

يعمل هذا الرمز بالفعل. ويعمل بشكل صحيح. ولكن ما زلت أريد أن أجعلها أكثر أناقة قليلاً. يمكن القيام بذلك بطريقة بسيطة للغاية:


 extern alias Lib1; extern alias Lib2; using System; using SpaceOne=Lib1::Space; using SpaceTwo=Lib2::Space; 

الآن يمكنك استخدام بناء الجملة المعتاد والواضح:


 var globe1 = new SpaceOne.Globe() var globe2 = new SpaceTwo.Globe() 

اختبر


دعونا اختبار البومة لدينا:



كما ترى ، عملت الشفرة بشكل جيد وبدون أخطاء. تم دمج البوم والكرات بنجاح!


يتوفر نموذج التعليمات البرمجية على GitHub

Source: https://habr.com/ru/post/ar421851/


All Articles