タイプを知る必要BinaryFormatter
はありません。メタデータはストリームに含まれています(大きくなりますが、ちょっと!)。ただし、タイプがわからないとキャストできません。多くの場合、このシナリオでは、一般的な既知のインターフェイス(非ジェネリックなど)とリフレクションを使用する必要があります。そしてそれはたくさんあります。IList
また、-に表示するタイプを知るための大きな要件を考えることはできませんPropertyGrid
-これは受け入れるのでobject
、提供するものを与えるだけBinaryFormatter
です。あなたがそこで見ている特定の問題はありますか?繰り返しになりますが、(一般的ではない)をチェックすることをお勧めしますが、これはチェックするものではないため、IList
心配する価値はありません!IList<T>
PropertyGrid
もちろん、必要に応じて(そのように)-そして使用して-きれいではないT
場合を見つけることができます。MakeGenericType()
Activator.CreateInstance
わかった; これは、オブジェクトやリストタイプについて何も知らないカスタム記述子を使用する方法です。本当に必要な場合は、リストアイテムをプロパティに直接展開できるため、この例では2つの偽のプロパティ(「Fred」と「Wilma」)が表示されます。これは余分な作業ですが、;-p
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
class Person
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public override string ToString() {
return Name;
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Person fred = new Person();
fred.Name = "Fred";
fred.DateOfBirth = DateTime.Today.AddYears(-23);
Person wilma = new Person();
wilma.Name = "Wilma";
wilma.DateOfBirth = DateTime.Today.AddYears(-20);
ShowUnknownObject(fred, "Single object");
List<Person> list = new List<Person>();
list.Add(fred);
list.Add(wilma);
ShowUnknownObject(list, "List");
}
static void ShowUnknownObject(object obj, string caption)
{
using(Form form = new Form())
using (PropertyGrid grid = new PropertyGrid())
{
form.Text = caption;
grid.Dock = DockStyle.Fill;
form.Controls.Add(grid);
grid.SelectedObject = ListWrapper.Wrap(obj);
Application.Run(form);
}
}
}
[TypeConverter(typeof(ListWrapperConverter))]
public class ListWrapper
{
public static object Wrap(object obj)
{
IListSource ls = obj as IListSource;
if (ls != null) obj = ls.GetList(); // list expansions
IList list = obj as IList;
return list == null ? obj : new ListWrapper(list);
}
private readonly IList list;
private ListWrapper(IList list)
{
if (list == null) throw new ArgumentNullException("list");
this.list = list;
}
internal class ListWrapperConverter : TypeConverter
{
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
public override PropertyDescriptorCollection GetProperties(
ITypeDescriptorContext context, object value, Attribute[] attributes) {
return new PropertyDescriptorCollection(
new PropertyDescriptor[] { new ListWrapperDescriptor(value as ListWrapper) });
}
}
internal class ListWrapperDescriptor : PropertyDescriptor {
private readonly ListWrapper wrapper;
internal ListWrapperDescriptor(ListWrapper wrapper) : base("Wrapper", null)
{
if (wrapper == null) throw new ArgumentNullException("wrapper");
this.wrapper = wrapper;
}
public override bool ShouldSerializeValue(object component) { return false; }
public override void ResetValue(object component) {
throw new NotSupportedException();
}
public override bool CanResetValue(object component) { return false; }
public override bool IsReadOnly {get {return true;}}
public override void SetValue(object component, object value) {
throw new NotSupportedException();
}
public override object GetValue(object component) {
return ((ListWrapper)component).list;
}
public override Type ComponentType {
get { return typeof(ListWrapper); }
}
public override Type PropertyType {
get { return wrapper.list.GetType(); }
}
public override string DisplayName {
get {
IList list = wrapper.list;
if (list.Count == 0) return "Empty list";
return "List of " + list.Count
+ " " + list[0].GetType().Name;
}
}
}
}