سؤال

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

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

مثال:

public enum CommandType : byte
{
    [PrimaryIdentifier("file"),
     AdditionalIdentifier("f"),
     CommandUsage("[<recipient>] [<filelocation>]")]
    FileTransferInitiation,

    [PrimaryIdentifier("accept"),
     AdditionalIdentifier("a")]
    AcceptFileTransfer,

    // ...
}

تنشأ مشكلتي عندما أحاول السماح بأسماء مستعارة متعددة للأمر الأساسي.لقد حاولت ذلك بطريقتين:من خلال السماح بالنسخ المكررة من AdditionalIdentifier السمة، أو عن طريق جعل وسيطة المنشئ في AdditionalIdentifier أ params string[].

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

هذا الأخير يعمل أيضا، ومع ذلك، فإنه يولد تحذير المترجم CS3016, ، ويقول أن هذا النهج غير متوافق مع CLS.من الواضح أن هذا لا يمنعني بالضرورة من الاستمرار في استخدامه، لكنني تعلمت أن أتعامل مع التحذيرات دائمًا على أنها أخطاء.

سؤالي الفعلي هو هل يجب أن أتجاهل اعتراضاتي على التكرارات وأستمر في استخدامها، أم أن هناك حلًا آخر يمكن استخدامه؟

شكرًا لك.

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

المحلول

أنا شخصياً سأتبع نهج السماح المتعدد:لا أعتقد أن "الضوضاء" ستكون مشكلة كبيرة إلا إذا كان لديك بالفعل عدد كبير من المعرفات لكل أمر.ولكن إذا لم يعجبك ذلك وتريد أن تظل متوافقًا مع CLS، فهناك حل آخر يتمثل في توفير مُنشئات محمّلة بشكل زائد لـ ExtraIdentifierAttribute:

public AdditionalIdentifierAttribute(string id) { ... }
public AdditionalIdentifierAttribute(string id1, string id2) { ... }
public AdditionalIdentifierAttribute(string id1, string id2, string id3) { ... }

الجانب السلبي هو أن هذا يقيدك بعدد محدد مسبقًا من المعرفات.

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

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

نصائح أخرى

ويمكنك أيضا استخدام "بارامس سلسلة [] الأسماء المستعارة" في المنشئ للسماح لقائمة وسيطة متغير:

[AttributeUsage(AttributeTargets.Method)]
class TestAttribute : Attribute
{
    public TestAttribute(params string[] aliases)
    {
        allowedAliases = aliases;
    }

    public string[] allowedAliases { get; set; }

}

وهذا من شأنه أن يسمح لك أن تفعل:

[Test("test1", "test2", "test3")]
static void Main(string[] args)

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

public class IdentifierAttribute
{
    public string Name { get; set; }
    public string Usage { get; set; }

    private string[] aliasArray;
    private string aliases;
    public string Aliases
    {
         get { return this.aliases; }
         set
         {
             this.aliases = value;
             this.aliasArray = value.Split(',').Trim();
         }
    }
}

وثم استخدامها مثل:

public enum CommandType : byte
{
     [Identifer( Name = "file", Aliases = "f", Usage = "..." )]
     FileTransferType,

     ...
}

ولكن من شأنه أن نهج آخر يكون لديها سمة اتخاذ مجموعة من السلاسل كمعلمة منشئ - وبهذه الطريقة، يمكنك الحصول على مترجم لتحليل مجموعة لك (على حساب لأكثر من المادة اللزجة قليلا عند تطبيق سمة) وهكذا :

[Identifiers(new string[] {"Bill", "Ben", "Ted"})]

وهناك مثال سريع 'ن القذرة لتنفيذ واستخدام تلك الطريقة يبدو مثل هذا:

using System;
using System.Collections.ObjectModel;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            SomeClass.TellMeAboutYourself();
        }
    }
    public class Identifiers : Attribute
    {
        private string[] names;
        public Identifiers(string[] someNames)
        {
            names = someNames;
        }
        public ReadOnlyCollection<string> Names { get { return new ReadOnlyCollection<string>(names); } }
    }
    [Identifiers(new string[] {"Bill", "Ben", "Ted"})]
    static class SomeClass
    {
        public static void TellMeAboutYourself()
        {
            Identifiers theAttribute = (Identifiers)Attribute.GetCustomAttribute(typeof(SomeClass), typeof(Identifiers));
            foreach (var s in theAttribute.Names)
            {
                Console.WriteLine(s);
            }
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top