كيف يمكنك الحصول على مساحة الاسم الجذر للتجميع؟

StackOverflow https://stackoverflow.com/questions/96317

  •  01-07-2019
  •  | 
  •  

سؤال

نظرا لمثال System.Reflection.Assembly.

هل كانت مفيدة؟

المحلول

غير ممكن.لا شيء يحدد مساحة الاسم "الجذر".مساحة الاسم الافتراضية في الخيارات هي شيء خاص بالاستوديو المرئي، وليس شيء .net

نصائح أخرى

لقد واجهت هذه المعضلة عدة مرات عندما أرغب في تحميل مورد من التجميع الحالي من خلال تدفق الموارد الواضح الخاص به.

الحقيقة هي أنه إذا قمت بتضمين ملف كمورد في التجميع الخاص بك باستخدام Visual Studio، فسيتم اشتقاق اسم المورد الظاهر الخاص به من مساحة الاسم الافتراضية للتجميع كما هو محدد في مشروع Visual Studio.

أفضل حل توصلت إليه (لتجنب ترميز مساحة الاسم الافتراضية كسلسلة في مكان ما) هو التأكد ببساطة من أن كود تحميل المورد الخاص بك يحدث دائمًا من داخل فئة موجودة أيضًا في مساحة الاسم الافتراضية ثم النهج شبه العام التالي يمكن استخدامها.

يقوم هذا المثال بتحميل مخطط مضمن.

XmlSchema mySchema;
string resourceName = "MyEmbeddedSchema.xsd";
string resourcesFolderName = "Serialisation";
string manifestResourceName = string.Format("{0}.{1}.{2}",
    this.GetType().Namespace, resourcesFolderName, resourceName);
using (Stream schemaStream = currentAssembly.GetManifestResourceStream(manifestResourceName))
    mySchema = XmlSchema.Read(schemaStream, errorHandler);

أنظر أيضا: كيفية الحصول على مساحة الاسم للتجميع؟

يحرر:لاحظت أيضًا إجابة مفصلة جدًا على السؤال الذي أجيب عليه http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/3a469f5d-8f55-4b25-ac25-4778f260bb7e

تعديل آخر في حالة ظهور أشخاص لديهم نفس السؤال:فكرة ممتازة لحل سؤال تحميل الموارد هنا: كيفية الحصول على مساحة الاسم الافتراضية لمشروع csproj (VS 2008)

يمكن أن يكون هناك أي عدد من مساحات الأسماء في تجميع معين، ولا شيء يتطلب أن تبدأ جميعها من جذر مشترك.أفضل ما يمكنك فعله هو التفكير في جميع الأنواع الموجودة في التجميع وإنشاء قائمة بمساحات الأسماء الفريدة الموجودة فيه.

لا تحتوي التجميعات بالضرورة على مساحة اسم جذر.مساحات الأسماء والتجميعات متعامدة.

ما قد تبحث عنه بدلاً من ذلك، هو العثور على نوع داخل هذا التجميع، ثم معرفة مساحة الاسم الخاصة به.

يجب أن تكون قادرًا على تحقيق ذلك عن طريق استخدام العضو GetExportedTypes() ثم استخدام خاصية Namespace من أحد مقابض النوع التي تم إرجاعها.

مرة أخرى، لا توجد ضمانات بأن جميع الأنواع موجودة في نفس مساحة الاسم (أو حتى في نفس التسلسل الهرمي لمساحة الاسم).

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

typeof(Root).Namespace;

بالتأكيد انتهى بي الأمر بملف غير مستخدم، لكنه نظيف.

GetType(frm).Namespace

frm هو نموذج بدء التشغيل

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

لا علاقة لمساحات الأسماء بالتجميعات - أي تعيين بين مساحة الاسم والفئات في التجميع يرجع فقط إلى اصطلاح التسمية (أو الصدفة).

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

بدلاً من تكرار الكود هنا، يرجى الاطلاع الحصول على اسم مساحة الاسم الافتراضي لأسلوب Assembly.GetManifestResourceStream()

أنا أستعمل typeof(App).Namespace في تطبيق WPF الخاص بي.تعد فئة التطبيق إلزامية لأي تطبيق WPF وهي موجودة في الجذر.

كان السؤال الذي دفعني إلى هنا هو، "إذا اتصلت بطرق كود المكتبة N بعمق وأريد مساحة اسم المشروع - على سبيل المثال تطبيق MVC الذي يعمل بالفعل - كيف يمكنني الحصول على ذلك؟"

مخترق قليلاً ولكن يمكنك فقط الحصول على تتبع المكدس والتصفية:

    public static string GetRootNamespace()
    {
        StackTrace stackTrace = new StackTrace();
        StackFrame[] stackFrames = stackTrace.GetFrames();
        string ns = null;
        foreach(var frame in stackFrames)
        {
            string _ns = frame.GetMethod().DeclaringType.Namespace;
            int indexPeriod = _ns.IndexOf('.');
            string rootNs = _ns;
            if (indexPeriod > 0)
                rootNs = _ns.Substring(0, indexPeriod);

            if (rootNs == "System")
                break;
            ns = _ns;
        }

        return ns;
    }

كل ما يفعله هذا هو الحصول على تتبع المكدس، وتشغيل الأساليب من أحدث استدعاءات إلى الجذر، والتصفية بحثًا عن System.out.بمجرد العثور على استدعاء النظام، فإنه يعلم أنه قد تم تجاوزه، ويعيد لك مساحة الاسم الموجودة فوقه مباشرة.سواء كنت تقوم بتشغيل اختبار الوحدة، أو تطبيق MVC، أو خدمة، فإن حاوية النظام ستكون أعمق بمستوى واحد من مساحة الاسم الجذر لمشروعك، لذا هاهو الأمر.

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

أنا متأكد من أنه يمكن تحسين ذلك - أنا متأكد من أن هذه الطريقة المبتذلة للقيام بالأشياء يمكن تحسينها بعدة طرق، والتحسينات مرحب بها.

إضافة إلى جميع الإجابات الأخرى هنا، ونأمل دون تكرار المعلومات، إليك كيفية حل هذه المشكلة باستخدام Linq.وضعي مشابه لإجابة ليزا.

الحل الخاص بي يأتي مع التحذيرات التالية:

  • أنت تستخدم Visual Studio ولديك مساحة اسم جذر محددة لمشروعك، والتي أفترض أنها ما تطلبه نظرًا لأنك تستخدم المصطلح "مساحة الاسم الجذر"
  • أنت لا تقوم بتضمين أنواع التشغيل المتداخل من التجميعات المشار إليها
Dim baseNamespace = String.Join("."c,
    Me.GetType().Assembly.ManifestModule.GetTypes().
        Select(Function(type As Type)
                    Return type.Namespace.Split("."c)
                End Function
        ).
        Aggregate(Function(seed As String(), splitNamespace As String())
                        Return seed.Intersect(splitNamespace).ToArray()
                    End Function
        )
)

هنا طريقة بسيطة إلى حد ما للحصول على مساحة الاسم الجذر لمشروع موقع ويب.

''' <summary>
''' Returns the namespace of the currently running website
''' </summary>
Public Function GetWebsiteRootNamespace() As String
    For Each Asm In AppDomain.CurrentDomain.GetAssemblies()
        If Asm Is Nothing OrElse Asm.IsDynamic Then Continue For

        For Each Typ In Asm.GetTypes
            If Typ Is Nothing OrElse Typ.Name Is Nothing Then Continue For
            If Typ.Name = "MyProject" Then Return Typ.Namespace.Split("."c)(0)
        Next
    Next

    Return Nothing
End Function

يؤدي هذا ببساطة إلى التحقق من كافة التجميعات المحملة لنوع "MyProject" وإرجاع مساحة الاسم الجذر لهذا النوع.يعد هذا مفيدًا للتسجيل عندما يكون لديك مشاريع ويب متعددة في حل واحد يشارك نظام السجل.أمل أن هذا يساعد شخصاما.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top