Вставить в анонимный тип
У меня была следующая проблема сегодня, и мне было интересно, есть ли решение для моей проблемы.
Моя идея заключалась в том, чтобы создавать анонимные классы и использовать их в качестве источника данных для 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");
}
Это прекрасно работает до сих пор.
Проблема, с которой я столкнулась, состоит в том, чтобы вывести Id из свойства "Current" для BindingSource, потому что я не могу вернуть его обратно в анонимный тип:
private void cmdOK_Click(object sender, EventArgs e)
{
var option = (???)bsOptions.Current;
}
Я думаю, что нет способа узнать тип "Текущий" и получить доступ к свойству "Идентификатор"?
Может быть, у кого-то есть хорошее решение...
Я знаю, что есть другие (а также лучшие) способы получить Id (Reflection, чтение значения из ComboBox, не используя анонимные tpyes,...) Я просто любезен, если можно получить Type bsOptions.Current элегантным способом.
Ответы
Ответ 1
Обратите внимание, что согласно комментарию, я просто хотел бы отметить, что я тоже рекомендую использовать реальный тип, когда вам нужно передать его вокруг программы, как это. Анонимные типы должны действительно использоваться только локально в одном методе за один раз (по моему мнению), но в любом случае здесь остальная часть моего ответа.
Вы можете сделать это, используя хитрость, обманув компилятор, чтобы сделать правильный тип для вас:
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);
Но мы действительно раздвигаем границы здесь. Используйте реальный тип, он будет выглядеть и чувствовать себя чище.
Ответ 2
Вместо того, чтобы выполнять произвольный тип, попробуйте использовать динамический тип.
Ваш обработчик событий будет выглядеть примерно так:
private void cmdOK_Click(object sender, EventArgs e)
{
dynamic option = bsOptions.Current;
if (option.Id == 1) { doSomething(); }
else { doSomethingElse(); }
}
Ответ 3
Чтобы процитировать MSDN:
Анонимный тип не может быть добавлен к любому интерфейсу или типу, кроме объекта.
Ответ 4
В С# 3.0 это невозможно. Вам придется подождать С# 4.0, который позволяет получать доступ к свойствам во время выполнения, используя "динамические" переменные.
Ответ 5
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);
Ответ 6
вы можете попробовать следующее:
private void cmdOK_Click(object sender, EventArgs e)
{
var option = Cast(bsOptions.Current, new { Id = 0, Option = "", Description = "" });
}
см. Не удается вернуть анонимный тип из метода? В самом деле?
Ответ 7
Вы также можете объявить массив анонимных типов непосредственно с этим синтаксисом:
var data = new [] {
new {Id = 0, Name = "Foo"},
new {Id = 42, Name = "Bar"},
};
Ответ 8
JSON облегчает управление, может помочь вам.
string FirstName = "M. Hamza";
string LastName = "Rajput";
int Age = 25;
var payload = new
{
FirstName,
LastName,
Age
};
Console.WriteLine(payload.FirstName);
DynamicFunc(payload);
JSONFunc(JObject.FromObject(payload));
Теперь у нас есть два способа, один с динамическим, а другой - JSON.
private void DynamicFunc(dynamic payload)
{
Console.WriteLine(payload.FirstName);
}
private void JSONFunc(JObject payload)
{
Console.WriteLine(payload["FirstName"]);
}
Если у вас возникнут проблемы, дайте мне знать. Удачи