Вы попробовали gdb-w cygwin gdb. Это - supossed для имения интерфейса окон, который работает довольно хорошо.
единственная проблема, которую я нашел, состоит в том, что на моей существующей машине это не выполняло тот путь, пока я не установил ddd. Я подозреваю, что это требует tcltk, который был установлен, когда я установил ddd.
С BinaryFormatter
вам не требуется , чтобы знать тип; метаданные включены в поток (увеличивая его, но эй!). Однако вы не можете преобразовать , если не знаете тип. Часто в этом сценарии вам приходится использовать общеизвестные интерфейсы (неуниверсальные , IList
и т.д.) и отражение. И много всего.
Я также не могу придумать огромного требования знать тип, отображаемый в PropertyGrid
- поскольку он принимает объект
, просто укажите, что 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;
}
}
}
}
Если сериализатор, который вы используете, не сохраняет тип - по крайней мере, вы должны сохранить тип T
вместе с данными и используйте их для создания общего списка рефлексивно:
//during storage:
Type elementType = myList.GetType().GetGenericTypeDefinition().GetGenericArguments[0];
string typeNameToSave = elementType.FullName;
//during retrieval
string typeNameFromDatabase = GetTypeNameFromDB();
Type elementType = Type.GetType(typeNameFromDatabase);
Type listType = typeof(List<>).MakeGenericType(new Type[] { elementType });
Теперь у вас есть listType
, который является точным List
, который вы использовали (скажем, Список
). Вы можете передать этот тип в процедуру десериализации.