使用DialogPage将数组存储在选项中 [英] Store array in options using DialogPage

查看:99
本文介绍了使用DialogPage将数组存储在选项中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我需要将任何数组存储在刚刚从模板中刚创建的扩展中.

Assume that I need to store any array in the extension just freshly created from the template.

我刚刚创建了一个新的 VSIX 项目,向其中添加了 VSPackage ,然后添加了选项页面网格(DialogPage).然后,我按照回答类似问题的说明进行操作: DialogPage-字符串数组不持久.

I just created new VSIX project, added VSPackage to it, then added option page grid (DialogPage). Then I followed instructions from answers to a similar question: DialogPage - string array not persisted.

并且,出于演示目的,我们还使用自定义类型转换器添加int[]数组和普通int.

And, for demonstration purposes, let's also add int[] array and plain int with custom type converter.

// [standard attributes]
[ProvideOptionPage(typeof(OptionPageGrid),
"My Category", "My Grid Page", 0, 0, true)]
public sealed class FooBarVSPackage : Package
{
    // standard code
}

public class OptionPageGrid : DialogPage
{
    // [typical attributes]
    [TypeConverter(typeof(StringArrayConverter))]
    public string[] Foos
    { get; set; }

    // [typical attributes]
    [TypeConverter(typeof(CustomIntConverter))]
    public int Bar
    { get; set; }

    // [typical attributes]
    [TypeConverter(typeof(IntArrayConverter))]
    public int[] Bazes
    { get; set; }
}

class StringArrayConverter : TypeConverter
{
    // exact copy of code from similar question/answer mentioned above
}

public class IntArrayConverter : TypeConverter
{
    private const string delimiter = "#@#";

    // CanConvertFrom, ConvertTo, etc. overridden in similar fashion
}

public class CustomIntConverter : TypeConverter
{
    // CanConvertFrom() overridden
    // CanConvertTo() overridden

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        var v = value as string;
        return int.Parse(v.TrimStart('*'));
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        var v = (int)value;
        return v.ToString().PadLeft(25, '*');
    }
}

当我编辑这些选项时,我可以看到转换器确实起作用:

When I edit those options, I can see that the converter really works:

但是在我重新打开它之后,其中两个值消失了!仅普通int保留:

But after I reopen it, two of the values gone! Only plain int persisted:

还有一件奇怪的事情:TypeConverter方法的调用方式和时间.在整个会话期间,从不调用CanConvertTo(). CanConvertFrom()ConvertTo()经常以预期的方式或多或少地被调用.当直接编辑选项的字符串表示形式时,ConvertFrom()仅被称为 ,即完全不参与加载/保存选项!

There is also one strange thing: how and when TypeConverter methods are called. CanConvertTo() is never called during the whole session. CanConvertFrom() and ConvertTo() are called often and more or less in expected fashion. And ConvertFrom() is called only when the string representation of the option is edited directly, i.e. it doesn't participate in loading/saving options at all!

我不确定,但是感觉int选项存储为int并仅在选项GUI中从/转换为string,而 array 选项只是默默地尝试执行相同操作失败.

I'm not sure, but it feels a bit like int option is stored as int and turned from/into string only in options GUI, while array options just silently fail trying to do the same.

PS:如果您想直接亲自处理该示例,请参见以下示例项目的GitHub存储库:

P.S.: If you want to directly play with the example personally, here is a GitHub repo with the example project in question: FooBarVSIXProject

推荐答案

花了几个小时尝试修复损坏的易用"机制(本身就是损坏的或其文档)之后,我意识到,与其浪费时间,我不应该只是将一个抽象层向下扩展,并完全按照自己的意愿进行操作DialogPage机制自动执行.

After spending several hours trying to fix broken "easy to use" mechanism (either itself is broken or its documentation), I realized that instead of wasting time, I should have descend just one abstraction layer down and do exactly what I wanted DialogPage mechanism do automatically.

人们希望DialogPage应该将字符串表示形式(通过类型转换器获得)保存/加载到用户设置存储(或类似名称),当其

One would expect that DialogPage should save/load the string representation (obtained through type converter) into/from User Settings Store (or something like that) when its SaveSettingsToStorage() and LoadSettingsFromStorage() are called. Since it refuses to do so and those methods are virtual, we can do exactly that ourselves:

public class OptionPageGrid : DialogPage
{
    const string collectionName = "FooBarVSIX";

    [Category("General")]
    [DisplayName("Foos")]
    [Description("Bla Foo Bla")]
    // note that TypeConverter attribute is removed,
    // because it's not relevant anymore
    public string[] Foos
    { get; set; }

    // Bar and Bazes properties missed out to make this example shorter

    public override void SaveSettingsToStorage()
    {
        base.SaveSettingsToStorage();

        var settingsManager = new ShellSettingsManager(ServiceProvider.GlobalProvider);
        var userSettingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings);

        if (!userSettingsStore.CollectionExists(collectionName))
            userSettingsStore.CreateCollection(collectionName);

        var converter = new StringArrayConverter();
        userSettingsStore.SetString(
            collectionName,
            nameof(Foos),
            converter.ConvertTo(this.Foos, typeof(string)) as string);
        // save Bazes in similar way
    }

    public override void LoadSettingsFromStorage()
    {
        base.LoadSettingsFromStorage();

        var settingsManager = new ShellSettingsManager(ServiceProvider.GlobalProvider);
        var userSettingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings);

        if (!userSettingsStore.PropertyExists(collectionName, nameof(Foos)))
            return;

        var converter = new StringArrayConverter();
        this.Foos = converter.ConvertFrom(
            userSettingsStore.GetString(collectionName, nameof(Foos))) as string[];
        // load Bazes in similar way
    }
}


现在,当然,如果您采用这种方式,则实际上不必编写和使用TypeConverter.您可以将序列化逻辑直接嵌入到这些方法中或任何地方.


Now, of course, if you do it this way, you don't have to write and use TypeConverter, actually. You can just embed serialization logic right into those methods, or anywhere.

此外,您可以直接将数据序列化为二进制格式,并使用 SetMemoryStream()进行保存.

Also, you can serialize your data just right into binary format and use SetMemoryStream() to save it.

这篇关于使用DialogPage将数组存储在选项中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆