سؤال

لدي حاليا هذا النوع من التعليمات البرمجية:

private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
    if (MainObject is SomeClassType1)
    {
        SomeClassType1 HelpObject = (SomeClassType1)MainObject;
        HelpObject.Property1 = Arg1;
        HelpObject.Property2 = Arg2;
    }
    else if (MainObject is SomeClassType2)
    {
        SomeClassType2 HelpObject = (SomeClassType2)MainObject;
        HelpObject.Property1 = Arg1;
        HelpObject.Property2 = Arg2;
    }
}

على افتراض أن someclasstype1 و someclasstype2 لها نفس مجموعة الخصائص التي أريد تعيينها (على الرغم من أنها قد تختلف في تلك الأخرى)، فهل من الممكن وضعها ديناميكيا Mainobject للنوع المناسب ثم تعيين القيمة، دون تكرار الرمز؟ هذا هو ما أود رؤيته في النهاية:

private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
    Type DynamicType = null;

    if (MainObject is SomeClassType1)
    {
        DynamicType = typeof(SomeClassType1);
    }
    else if (MainObject is SomeClassType2)
    {
        DynamicType = typeof(SomeClassType2);
    }

    DynamicType HelpObject = (DynamicType)MainObject;
    HelpObject.Property1 = Arg1;
    HelpObject.Property2 = Arg2;
}

من الواضح أن ج # يشكو من عدم القدرة على العثور على ديناميكي:

لا يمكن العثور على اسم نوع أو اسم الاسم "الديناميكي" (هل تفتقد استخدام التوجيه أو مرجع التجميع؟)

هل هذا شيء من هذا القبيل ممكن في C # 2.0؟ إذا كان الأمر فوضوي أكثر من رمزي الحالي، فمن لا أرى أي وقت في القيام بذلك، لكنني مهتم للغاية لمعرفة ذلك. شكرا!

تحرير: فقط للتوضيح، أفهم تماما أن تطبيق واجهة هو الحل الأنسب وربما صحيح. ومع ذلك، أنا مهتم بأكثر برؤية كيف يمكنني القيام بذلك دون تنفيذ واجهة. شكرا لردود رائعة!

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

المحلول

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

public interface IMyInterface
{
   public Foo Property1 {get; set;}
   public Bar Property2 {get;set;}
}

ثم، تأكد من إخبار كل فصولك بالمترجم الذي ينفذه تلك الواجهة الجديدة. أخيرا، استخدم طريقة عامة مع وسيطة من النوع مقيدة بهذا التدخل:

private void FillObject<T>(T MainObject, Foo Arg1, Bar Arg2) 
    where T : IMyInterface
{
    MainObject.Property1 = Arg1;
    MainObject.Property2 = Arg2;
}

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

نصائح أخرى

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

كتبت إطارا صغيرا للتحول عن الأنواع التي تجعل بناء الجملة موجزة أكثر قليلا. يسمح لك بكتابة رمز مثل ما يلي.

TypeSwitch.Do(
    sender,
    TypeSwitch.Case<Button>(
        () => textBox1.Text = "Hit a Button"),
    TypeSwitch.Case<CheckBox>(
        x => textBox1.Text = "Checkbox is " + x.Checked),
    TypeSwitch.Default(
        () => textBox1.Text = "Not sure what is hovered over"));

مشاركة مدونة: http://blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx.

هل ستكون قادرا على إجراء تغييرات على Someclasstype1، Someclasstype2 إلخ؟ إذا كانت الإجابة بنعم، سأقترح عليك إنشاء واجهة تحتوي على خصائص شائعة ثم Typecast لهذه الواجهة FillObject() لتعيين الخصائص.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SO566510
{
    interface IMyProperties
    {
        int Property1 { get; set; }
        int Property2 { get; set; }
    }

    class SomeClassType1 : IMyProperties
    {
        public int Property1 { get; set; }
        public int Property2 { get; set; }
    }

    class SomeClassType2 : IMyProperties
    {
        public int Property1 { get; set; }
        public int Property2 { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var obj1 = new SomeClassType1();
            var obj2 = new SomeClassType2();

            FillObject(obj1, 10, 20);
            FillObject(obj2, 30, 40);

        }

        private static void FillObject(IMyProperties objWithMyProperties
                                   , int arg1, int arg2)
        {
            objWithMyProperties.Property1 = arg1;
            objWithMyProperties.Property2 = arg2;
        }
    }
}
private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
    Type t = MainObject.GetType();

    t.GetProperty("Property1").SetValue(MainObject, Arg1, null);
    t.GetProperty("Property2").SetValue(MainObject, Arg2, null);
}

بعض الافكار:

  1. هل لديك كلا النوعين يرثين من نفس النوع الذي يحتوي على الخصائص الشائعة
  2. لديك كلا النوعين ينفذون نفس الواجهة التي تحتوي على الخصائص الشائعة
  3. استخدام التفكير لتعيين الخصائص بدلا من إعدادها مباشرة (ربما يكون هذا أكثر قباشرة مما يستحق)
  4. استخدام الجديد متحرك خاصية, ، لم أحاول ذلك، ولكن يبدو أنه قد يعالج مشكلتك

بدلا من محاولة الإدلاء، ربما يمكنك تجربة تحديد الخصائص باستخدام التفكير.

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

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