Typelite:为什么Dictionary <string,object =“”>映射到KeyValuePair而不是任何或[index:string]:any </string,>

时间:2014-01-25 12:26:09

标签: typelite

我有一个班级,

public class Instance : IResource
{
   public Dictionary<string, object> Value { get; set; }

并将其映射到

interface Instance {
   Value: System.Collections.Generic.KeyValuePair[];

interface KeyValuePair {
   Key: any;
   Value: any;
}

我原本预计

interface Instance {
   Value: any;

interface Instance {
   Value: {[index:string]:any};

如何更改代?

另外,如何跳过代中的名称空间?

3 个答案:

答案 0 :(得分:8)

快速而肮脏的解决方法是使用正则表达式来改变输出:

使用

<#= Regex.Replace( ts.Generate(TsGeneratorOutput.Properties)
        , @":\s*System\.Collections\.Generic\.KeyValuePair\<(?<k>[^\,]+),(?<v>[^\,]+)\>\[\];"
        , m=>": {[key: "+m.Groups["k"].Value+"]: "+m.Groups["v"].Value+"};"
        , RegexOptions.Multiline)
#>

转换字段

    myField: System.Collections.Generic.KeyValuePair<string,OtherClass>[];

    myField: {[key: string]: OtherClass};

答案 1 :(得分:4)

集合类型(实现IEnumerable的任何类型)都将转换为数组。 Dictionary<>实现IEnumerable<KeyValuePair<>>,因此转换为数组。然后将item-type扩展为其完全限定名称(FQN):System.Collections.Generic.KeyValuePair

使用类型转换器可以更改类型名称,但不能更改FQN。所以它只适用于本地类型。对于字典,您无法通过继承更改项类型。

您可以创建新的字典类型,而无需继承Dictionary<>。解决此问题的另一种方法是使用Type Formatters:

ts.WithConvertor<Dictionary<string,object>>(t => {
    // Embed the real type in $
    // "System.Collections.Generic.${ [key: string]: any }$[]"
    return "${ [key: string]: any }$";
});
ts.WithFormatter((string memberTypeName, bool isMemberCollection) => {
    // Extract the content inside $
    string[] pieces = memberTypeName.Split('$');
    if (pieces.Length == 3) return pieces[1];
    // Default behaviour
    return memberTypeName + (isMemberCollection ? "[]" : "");
});

答案 2 :(得分:2)

这是一个更为通用(和更新)的解决方案,它基于Markus Jarderot的答案:

sessionStorage

像这样使用:

var SSitems = JSON.parse(sessionStorage.idstores) || {},
    all$items = []; // Store all created $() items

function create$item( item ){
  var $item = $("<div/>", {
    // (P.S: DIV cannot have TYPE nor NAME properties)
    id    : "store_"+ item.idstores,
    class : "store",
    html  : `<div class='store-img'>
              <img src='${item.storeImageUrl}'>
            </div>
            <div class='store-text2'>
              <h3>${item.pointsNeeded} Hero Points etc...</h3>
            </div>`,
    on    : {
      click : function(){
          SSitems[item.idstores] = item;
          sessionStorage.idstores = JSON.stringify(SSitems);
          console.dir( JSON.parse(sessionStorage.idstores) );
      }
    }
  });
  // Now that the div is created and click handler is assigned
  all$items.push( $item );
}

function showStores(userArray) {
  userArray.forEach(create$item);       // Loop / create elements
  $('#storeItems').append( all$items ); // Append only once!
};

// TEST
var data = [
  {idstores:0,  storeImageUrl:"http://placehold.it/50x50", pointsNeeded:30},
  {idstores:23, storeImageUrl:"http://placehold.it/50x50", pointsNeeded:130}
];
showStores(data);

N.B。这只修复了具有字典类型的属性(或字段)的类型签名。另外static void RegisterDictionaryMemberFormatter(this TsGenerator tsGenerator) { tsGenerator.SetMemberTypeFormatter((tsProperty, memberTypeName) => { var dictionaryInterface = tsProperty.PropertyType.Type.GetInterface(typeof(IDictionary<,>).Name) ?? tsProperty.PropertyType.Type.GetInterface(typeof(IDictionary).Name); if (dictionaryInterface != null) { return tsGenerator.GetFullyQualifiedTypeName(new TsClass(dictionaryInterface)); } else { return tsGenerator.DefaultMemberTypeFormatter(tsProperty, memberTypeName); } }); } // and if you like the fluent syntax... static TypeScriptFluent WithDictionaryMemberFormatter(this TypeScriptFluent typeScriptFluent) { typeScriptFluent.ScriptGenerator.RegisterDictionaryMemberFormatter(); return typeScriptFluent; } 的定义是自动发出,您必须手动添加它们:

var ts = TypeLite.TypeScript.Definitions().For(typeof(SomeClass).Assembly);
ts.ScriptGenerator.RegisterDictionaryMemberFormatter();

// alternatively with fluent syntax:

var ts = TypeLite.TypeScript.Definitions()
    .For(typeof(SomeClass).Assembly)
    .WithDictionaryMemberFormatter();