سؤال

وكان لي المشكلة التالية اليوم، وأنا أتساءل عما إذا كان هناك حل لمشكلتي.

وكانت فكرتي لبناء فصول مجهولة المصدر واستخدامه بمثابة مصدر بيانات لWinForm BindingSource:

public void Init()
{
    var option1 = new
                  {
                      Id = TemplateAction.Update,
                      Option = "Update the Templates",
                      Description = "Bla bla 1."
                  };

    var option2 = new
                  {
                      Id = TemplateAction.Download,
                      Option = "Download the Templates",
                      Description = "Bla bla 2."
                  };

    var list = new[] {option1, option2}.ToList();

    bsOptions.DataSource = list; // my BindingSource

    // cboTemplates is a ComboBox
    cboTemplates.DataSource = bsOptions; 
    cboTemplates.ValueMember = "Id";
    cboTemplates.DisplayMember = "Option";

    lblInfoTemplates.DataBindings.Add("Text", bsOptions, "Description");
}

وهذا يعمل بشكل جيد حتى الآن.

والمشكلة كان لي هو الحصول على رقم من الممتلكات "الحالية" للBindingSource، لأنني لا يمكن أن يلقي مرة أخرى إلى نوع مجهول:

private void cmdOK_Click(object sender, EventArgs e)
{
    var option = (???)bsOptions.Current;
}

وأعتقد أن هناك أي وسيلة لمعرفة نوع من "التيار" والوصول إلى "رقم" الملكية؟ ربما شخص ما لديه حلا جيدا ...

وأعرف أن هناك أخرى (وأيضا أفضل) طرق للحصول على رقم (التأمل والقراءة القيمة من تحرير وسرد، لا تستخدم tpyes مجهولة، ...) أنا مجرد كريوس إذا كان من الممكن أن يحصل نوع من من bsOptions.Current بطريقة أنيقة.

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

المحلول

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


ويمكنك القيام بذلك باستخدام خدعة، عن طريق خداع المترجم إلى استنتاج النوع المناسب لك:

using System;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new { Id = 1, Name = "Bob" };
            TestMethod(a);

            Console.Out.WriteLine("Press enter to exit...");
            Console.In.ReadLine();
        }

        private static void TestMethod(Object x)
        {
            // This is a dummy value, just to get 'a' to be of the right type
            var a = new { Id = 0, Name = "" };
            a = Cast(a, x);
            Console.Out.WriteLine(a.Id + ": " + a.Name);
        }

        private static T Cast<T>(T typeHolder, Object x)
        {
            // typeHolder above is just for compiler magic
            // to infer the type to cast x to
            return (T)x;
        }
    }
}

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

private static T CastTo<T>(this Object value, T targetType)
{
    // targetType above is just for compiler magic
    // to infer the type to cast value to
    return (T)value;
}

والاستعمال:

var value = x.CastTo(a);

ولكن نحن ندفع حقا حدود هنا. استخدام نوع الحقيقي، انها سوف تبدو وتشعر نظافة كذلك.

نصائح أخرى

وبدلا من صب إلى نوع مخصص حاول استخدام نوع الديناميكي.

وسيكون معالج الحدث الخاص بك تبدو شيئا مثل هذا:

private void cmdOK_Click(object sender, EventArgs e)
{
    dynamic option = bsOptions.Current;
    if (option.Id == 1) { doSomething(); }
      else { doSomethingElse(); }
}

لأقتبس MSDN :

<اقتباس فقرة>   

لا يمكن ان يلقي نوع مجهول إلى أي واجهة أو نوع باستثناء الكائن.

في C # 3.0، وهذا غير ممكن. سوف تضطر إلى الانتظار لC # 4.0، والذي يسمح الوصول إلى خصائص في وقت التشغيل باستخدام متغيرات "ديناميكية".

public class MyExtensMethods{

    public static T GetPropertyValue<T>(this Object obj, string property)
    {
        return (T)obj.GetType().GetProperty(property).GetValue(obj, null);
    }
}

class SomeClass
{
    public int ID{get;set;}
    public int FullName{get;set;}
}


// casts obj to type SomeClass
public SomeClass CastToSomeClass(object obj)
{
     return new SomeClass()
     {
         ID = obj.GetPropertyValue<int>("Id"),
         FullName = obj.GetPropertyValue<string>("LastName") + ", " + obj.GetPropertyValue<string>("FirstName")
     };
}

و.... ثم يلقي كنت ستفعل:

var a = new { Id = 1, FirstName = "Bob", LastName="Nam" };
SomeClass myNewVar = CastToSomeClass(a);

ويمكنك أن تجرب هذا:

private void cmdOK_Click(object sender, EventArgs e)
{
    var option = Cast(bsOptions.Current, new { Id = 0, Option = "", Description = "" });
}

وراجع: لا يمكن إرجاع نوع مجهول من طريقة؟ حقا؟

ويمكنك أيضا الإعلان عن مجموعة من أنواع مجهولة مباشرة مع أن بناء الجملة:

var data = new [] {
  new {Id = 0, Name = "Foo"},
  new {Id = 42, Name = "Bar"},
};
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top