T4->;C#类到Typescript中的淘汰视图模型

T4->;C#类到Typescript中的淘汰视图模型,c#,knockout.js,typescript,t4,typelite,C#,Knockout.js,Typescript,T4,Typelite,我正在寻找某种T4或类似的方法来获取C#类,并以强类型的方式生成数据接口和视图模型 我发现typelite在界面上工作得很好,但我也在寻找能够处理viewmodels(或除此之外)的东西 我发现这个项目看起来很棒: 但当然,它会生成javascript,而且在类型方面,包括枚举、继承等方面进行黑客攻击,并使其与typescript一起工作,这看起来并不简单 有人知道这样做的项目吗 如果没有,有没有关于如何构建的技巧?我不是T4方面的专家,即使在VisualStudio中使用工具使T4编辑变得不那

我正在寻找某种T4或类似的方法来获取C#类,并以强类型的方式生成数据接口和视图模型

我发现typelite在界面上工作得很好,但我也在寻找能够处理viewmodels(或除此之外)的东西

我发现这个项目看起来很棒:

但当然,它会生成javascript,而且在类型方面,包括枚举、继承等方面进行黑客攻击,并使其与typescript一起工作,这看起来并不简单

有人知道这样做的项目吗

如果没有,有没有关于如何构建的技巧?我不是T4方面的专家,即使在VisualStudio中使用工具使T4编辑变得不那么糟糕,它看起来也相当坚不可摧


谢谢

我这样做是为了让我的DTO合同可以从javascript中获得,也许它可以帮助你

<#@ template debug="true" hostSpecific="true" #>
<#@ output extension=".js" #>
<#@ Assembly Name="System.Core" #>
<#@ Assembly Name="System.Windows.Forms" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="EnvDTE" #>
<#@ include file="..\T4\Automation.ttinclude"#><#
var project = VisualStudioHelper.GetProject("MyApp.Core.Contracts");      
var contracts = GetSubClasses("MyApp.Core.Contracts.Commands.Command", project)
    .Concat(GetSubClasses("MyApp.Core.Contracts.Queries.Query", project));

#>(function(MyApp) {
    function buildContract(contract) {
        return { type: contract.constructor.type, data: ko.toJSON(contract) };
    }
    var url = "api/commandQuery";
    MyApp.cqrs = {
        sendQuery: function(query, callback) {
            $.getJSON(url, buildContract(query), callback);
        },
        sendCommand: function(command) {
            MyApp.utils.post(url, buildContract(command));
        }
    };
<#


foreach(var contract in contracts) {
        #>  
    <#
    foreach(var part in BuildNameSpace(contract)) {
        #><#= part #>
    <#
    }

    var properties = GetProperties(contract).Select(p => CamelCased(p.Name)).ToList();
    var args = string.Join(", ", properties);

    #>

    window.<#= contract.FullName #> = function(<#= args #>) {<#
    foreach(var property in properties) {#>

        this.<#= property #> = <#= property #>;<#
    }
    #>

    };
    window.<#= contract.FullName #>.type = "<#= contract.FullName #>";
<#
}
#>
})(window.MyApp = window.MyApp || {});
<#+

private static IEnumerable<string> BuildNameSpace(CodeClass @class)
{
    return BuildNameSpace(@class.Namespace.Name.Split('.'), "window", new List<string>());
}            

private static IEnumerable<string> BuildNameSpace(IEnumerable<string> @namespace, string parent, List<string> parts)
{
    var part = @namespace.FirstOrDefault();
    if (part == null) return parts;

    var current = string.Format("{0}.{1}", parent, part);
    parts.Add(string.Format("{0} = ({0} || {{}});", current));
    return BuildNameSpace(@namespace.Skip(1), current, parts);
}

public IEnumerable<CodeClass> GetSubClasses(string baseClass, Project project)
{
    return VisualStudioHelper       
        .CodeModel
        .GetAllCodeElementsOfType(project.CodeModel.CodeElements, EnvDTE.vsCMElement.vsCMElementClass, false)
        .Cast<CodeClass>()
        .Where(c => GetInheritance(c).Any(b => b.FullName == baseClass) && !c.IsAbstract)
        .ToList(); 
}


public IEnumerable<CodeClass> GetInheritance(CodeClass @class) 
{
    return GetInheritance(@class, new List<CodeClass>());
}

public IEnumerable<CodeClass> GetInheritance(CodeClass @class, List<CodeClass> collection) 
{
    foreach(CodeClass @base in @class.Bases) 
    {
        collection.Add(@base);
        GetInheritance(@base, collection);
    }

    return collection;
}

public string CamelCased(string pascalCased) {
    return pascalCased.Substring(0, 1).ToLower() + pascalCased.Substring(1);
}

public IEnumerable<CodeProperty> GetProperties(CodeClass @class)
{
    if (@class == null) 
        return new List<CodeProperty>();

    var baseProperties = GetProperties(@class.Bases.Cast<CodeClass>().FirstOrDefault());

    return baseProperties.Concat(@class
        .Members
        .Cast<CodeElement>()
        .Where(ce => ce.Kind == vsCMElement.vsCMElementProperty)
        .Cast<CodeProperty>()
        .Where(p => p.Access == vsCMAccess.vsCMAccessPublic));
    }
 #>
请注意,它依赖于有形的T4编辑器模板

<#@ include file="..\T4\Automation.ttinclude"#>

我这样做是为了让我的DTO合同可以从javascript中获得,也许它可以帮助你

<#@ template debug="true" hostSpecific="true" #>
<#@ output extension=".js" #>
<#@ Assembly Name="System.Core" #>
<#@ Assembly Name="System.Windows.Forms" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="EnvDTE" #>
<#@ include file="..\T4\Automation.ttinclude"#><#
var project = VisualStudioHelper.GetProject("MyApp.Core.Contracts");      
var contracts = GetSubClasses("MyApp.Core.Contracts.Commands.Command", project)
    .Concat(GetSubClasses("MyApp.Core.Contracts.Queries.Query", project));

#>(function(MyApp) {
    function buildContract(contract) {
        return { type: contract.constructor.type, data: ko.toJSON(contract) };
    }
    var url = "api/commandQuery";
    MyApp.cqrs = {
        sendQuery: function(query, callback) {
            $.getJSON(url, buildContract(query), callback);
        },
        sendCommand: function(command) {
            MyApp.utils.post(url, buildContract(command));
        }
    };
<#


foreach(var contract in contracts) {
        #>  
    <#
    foreach(var part in BuildNameSpace(contract)) {
        #><#= part #>
    <#
    }

    var properties = GetProperties(contract).Select(p => CamelCased(p.Name)).ToList();
    var args = string.Join(", ", properties);

    #>

    window.<#= contract.FullName #> = function(<#= args #>) {<#
    foreach(var property in properties) {#>

        this.<#= property #> = <#= property #>;<#
    }
    #>

    };
    window.<#= contract.FullName #>.type = "<#= contract.FullName #>";
<#
}
#>
})(window.MyApp = window.MyApp || {});
<#+

private static IEnumerable<string> BuildNameSpace(CodeClass @class)
{
    return BuildNameSpace(@class.Namespace.Name.Split('.'), "window", new List<string>());
}            

private static IEnumerable<string> BuildNameSpace(IEnumerable<string> @namespace, string parent, List<string> parts)
{
    var part = @namespace.FirstOrDefault();
    if (part == null) return parts;

    var current = string.Format("{0}.{1}", parent, part);
    parts.Add(string.Format("{0} = ({0} || {{}});", current));
    return BuildNameSpace(@namespace.Skip(1), current, parts);
}

public IEnumerable<CodeClass> GetSubClasses(string baseClass, Project project)
{
    return VisualStudioHelper       
        .CodeModel
        .GetAllCodeElementsOfType(project.CodeModel.CodeElements, EnvDTE.vsCMElement.vsCMElementClass, false)
        .Cast<CodeClass>()
        .Where(c => GetInheritance(c).Any(b => b.FullName == baseClass) && !c.IsAbstract)
        .ToList(); 
}


public IEnumerable<CodeClass> GetInheritance(CodeClass @class) 
{
    return GetInheritance(@class, new List<CodeClass>());
}

public IEnumerable<CodeClass> GetInheritance(CodeClass @class, List<CodeClass> collection) 
{
    foreach(CodeClass @base in @class.Bases) 
    {
        collection.Add(@base);
        GetInheritance(@base, collection);
    }

    return collection;
}

public string CamelCased(string pascalCased) {
    return pascalCased.Substring(0, 1).ToLower() + pascalCased.Substring(1);
}

public IEnumerable<CodeProperty> GetProperties(CodeClass @class)
{
    if (@class == null) 
        return new List<CodeProperty>();

    var baseProperties = GetProperties(@class.Bases.Cast<CodeClass>().FirstOrDefault());

    return baseProperties.Concat(@class
        .Members
        .Cast<CodeElement>()
        .Where(ce => ce.Kind == vsCMElement.vsCMElementProperty)
        .Cast<CodeProperty>()
        .Where(p => p.Access == vsCMAccess.vsCMAccessPublic));
    }
 #>
请注意,它依赖于有形的T4编辑器模板

<#@ include file="..\T4\Automation.ttinclude"#>

我这样做是为了让我的DTO合同可以从javascript中获得,也许它可以帮助你

<#@ template debug="true" hostSpecific="true" #>
<#@ output extension=".js" #>
<#@ Assembly Name="System.Core" #>
<#@ Assembly Name="System.Windows.Forms" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="EnvDTE" #>
<#@ include file="..\T4\Automation.ttinclude"#><#
var project = VisualStudioHelper.GetProject("MyApp.Core.Contracts");      
var contracts = GetSubClasses("MyApp.Core.Contracts.Commands.Command", project)
    .Concat(GetSubClasses("MyApp.Core.Contracts.Queries.Query", project));

#>(function(MyApp) {
    function buildContract(contract) {
        return { type: contract.constructor.type, data: ko.toJSON(contract) };
    }
    var url = "api/commandQuery";
    MyApp.cqrs = {
        sendQuery: function(query, callback) {
            $.getJSON(url, buildContract(query), callback);
        },
        sendCommand: function(command) {
            MyApp.utils.post(url, buildContract(command));
        }
    };
<#


foreach(var contract in contracts) {
        #>  
    <#
    foreach(var part in BuildNameSpace(contract)) {
        #><#= part #>
    <#
    }

    var properties = GetProperties(contract).Select(p => CamelCased(p.Name)).ToList();
    var args = string.Join(", ", properties);

    #>

    window.<#= contract.FullName #> = function(<#= args #>) {<#
    foreach(var property in properties) {#>

        this.<#= property #> = <#= property #>;<#
    }
    #>

    };
    window.<#= contract.FullName #>.type = "<#= contract.FullName #>";
<#
}
#>
})(window.MyApp = window.MyApp || {});
<#+

private static IEnumerable<string> BuildNameSpace(CodeClass @class)
{
    return BuildNameSpace(@class.Namespace.Name.Split('.'), "window", new List<string>());
}            

private static IEnumerable<string> BuildNameSpace(IEnumerable<string> @namespace, string parent, List<string> parts)
{
    var part = @namespace.FirstOrDefault();
    if (part == null) return parts;

    var current = string.Format("{0}.{1}", parent, part);
    parts.Add(string.Format("{0} = ({0} || {{}});", current));
    return BuildNameSpace(@namespace.Skip(1), current, parts);
}

public IEnumerable<CodeClass> GetSubClasses(string baseClass, Project project)
{
    return VisualStudioHelper       
        .CodeModel
        .GetAllCodeElementsOfType(project.CodeModel.CodeElements, EnvDTE.vsCMElement.vsCMElementClass, false)
        .Cast<CodeClass>()
        .Where(c => GetInheritance(c).Any(b => b.FullName == baseClass) && !c.IsAbstract)
        .ToList(); 
}


public IEnumerable<CodeClass> GetInheritance(CodeClass @class) 
{
    return GetInheritance(@class, new List<CodeClass>());
}

public IEnumerable<CodeClass> GetInheritance(CodeClass @class, List<CodeClass> collection) 
{
    foreach(CodeClass @base in @class.Bases) 
    {
        collection.Add(@base);
        GetInheritance(@base, collection);
    }

    return collection;
}

public string CamelCased(string pascalCased) {
    return pascalCased.Substring(0, 1).ToLower() + pascalCased.Substring(1);
}

public IEnumerable<CodeProperty> GetProperties(CodeClass @class)
{
    if (@class == null) 
        return new List<CodeProperty>();

    var baseProperties = GetProperties(@class.Bases.Cast<CodeClass>().FirstOrDefault());

    return baseProperties.Concat(@class
        .Members
        .Cast<CodeElement>()
        .Where(ce => ce.Kind == vsCMElement.vsCMElementProperty)
        .Cast<CodeProperty>()
        .Where(p => p.Access == vsCMAccess.vsCMAccessPublic));
    }
 #>
请注意,它依赖于有形的T4编辑器模板

<#@ include file="..\T4\Automation.ttinclude"#>

我这样做是为了让我的DTO合同可以从javascript中获得,也许它可以帮助你

<#@ template debug="true" hostSpecific="true" #>
<#@ output extension=".js" #>
<#@ Assembly Name="System.Core" #>
<#@ Assembly Name="System.Windows.Forms" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="EnvDTE" #>
<#@ include file="..\T4\Automation.ttinclude"#><#
var project = VisualStudioHelper.GetProject("MyApp.Core.Contracts");      
var contracts = GetSubClasses("MyApp.Core.Contracts.Commands.Command", project)
    .Concat(GetSubClasses("MyApp.Core.Contracts.Queries.Query", project));

#>(function(MyApp) {
    function buildContract(contract) {
        return { type: contract.constructor.type, data: ko.toJSON(contract) };
    }
    var url = "api/commandQuery";
    MyApp.cqrs = {
        sendQuery: function(query, callback) {
            $.getJSON(url, buildContract(query), callback);
        },
        sendCommand: function(command) {
            MyApp.utils.post(url, buildContract(command));
        }
    };
<#


foreach(var contract in contracts) {
        #>  
    <#
    foreach(var part in BuildNameSpace(contract)) {
        #><#= part #>
    <#
    }

    var properties = GetProperties(contract).Select(p => CamelCased(p.Name)).ToList();
    var args = string.Join(", ", properties);

    #>

    window.<#= contract.FullName #> = function(<#= args #>) {<#
    foreach(var property in properties) {#>

        this.<#= property #> = <#= property #>;<#
    }
    #>

    };
    window.<#= contract.FullName #>.type = "<#= contract.FullName #>";
<#
}
#>
})(window.MyApp = window.MyApp || {});
<#+

private static IEnumerable<string> BuildNameSpace(CodeClass @class)
{
    return BuildNameSpace(@class.Namespace.Name.Split('.'), "window", new List<string>());
}            

private static IEnumerable<string> BuildNameSpace(IEnumerable<string> @namespace, string parent, List<string> parts)
{
    var part = @namespace.FirstOrDefault();
    if (part == null) return parts;

    var current = string.Format("{0}.{1}", parent, part);
    parts.Add(string.Format("{0} = ({0} || {{}});", current));
    return BuildNameSpace(@namespace.Skip(1), current, parts);
}

public IEnumerable<CodeClass> GetSubClasses(string baseClass, Project project)
{
    return VisualStudioHelper       
        .CodeModel
        .GetAllCodeElementsOfType(project.CodeModel.CodeElements, EnvDTE.vsCMElement.vsCMElementClass, false)
        .Cast<CodeClass>()
        .Where(c => GetInheritance(c).Any(b => b.FullName == baseClass) && !c.IsAbstract)
        .ToList(); 
}


public IEnumerable<CodeClass> GetInheritance(CodeClass @class) 
{
    return GetInheritance(@class, new List<CodeClass>());
}

public IEnumerable<CodeClass> GetInheritance(CodeClass @class, List<CodeClass> collection) 
{
    foreach(CodeClass @base in @class.Bases) 
    {
        collection.Add(@base);
        GetInheritance(@base, collection);
    }

    return collection;
}

public string CamelCased(string pascalCased) {
    return pascalCased.Substring(0, 1).ToLower() + pascalCased.Substring(1);
}

public IEnumerable<CodeProperty> GetProperties(CodeClass @class)
{
    if (@class == null) 
        return new List<CodeProperty>();

    var baseProperties = GetProperties(@class.Bases.Cast<CodeClass>().FirstOrDefault());

    return baseProperties.Concat(@class
        .Members
        .Cast<CodeElement>()
        .Where(ce => ce.Kind == vsCMElement.vsCMElementProperty)
        .Cast<CodeProperty>()
        .Where(p => p.Access == vsCMAccess.vsCMAccessPublic));
    }
 #>
请注意,它依赖于有形的T4编辑器模板

<#@ include file="..\T4\Automation.ttinclude"#>



T4非常简单。我建议您使用有形T4编辑器。它们有一个免费版本,它突出显示了与“生成代码”不同的“模板代码”。它真的很有用。我还推荐T4工具箱。我已经编写了几十个T4模板,但没有一个与您正在寻找的模板相关。您是否考虑过使用像Breeze.js这样的客户端数据库,这样您就不必在客户端和服务器上创建模型?Breeze的问题是它仍然不是强类型的。其全部目的是使所有内容都完全强类型化,因此任何地方的任何更改都将抛出编译时错误,而不是随机显示。通过使用t4 viewmodel生成器,即使您使用的是Breeze,您也可以对对象进行强强制转换,这样所有内容都可以在Typescript中进行强类型化。只是搞乱了它,它只是一个相当丑陋的文档,关于做一些简单的事情,比如循环类库中的所有内容并查找属性,然后我需要做一些事情,比如创建枚举,记住我已经创建了它们,处理继承等。试着变得懒惰,而不是重新发明轮子。“试着懒惰,而不是重新发明轮子。”-有时你必须发明一个不同的轮子,以使其适合你的业务需求(你已经注意到Breeze.js轮子并不真正适合)。T4非常简单。我建议你使用有形T4编辑器。他们有一个免费版,它突出了“模板代码”与“生成的代码”不同。它真的很有用。我还推荐T4工具箱。我已经编写了几十个T4模板,但没有一个与您正在寻找的模板相关。您是否考虑过使用像Breeze.js这样的客户端数据库,这样您就不必在客户端和服务器上创建模型?Breeze的问题是它仍然不是强类型的。其全部目的是使所有内容都完全强类型化,因此任何地方的任何更改都将抛出编译时错误,而不是随机显示。通过使用t4 viewmodel生成器,即使您使用的是Breeze,您也可以对对象进行强强制转换,这样所有内容都可以在Typescript中进行强类型化。只是搞乱了它,它只是一个相当丑陋的文档,关于做一些简单的事情,比如循环类库中的所有内容并查找属性,然后我需要做一些事情,比如创建枚举,记住我已经创建了它们,处理继承等。试着变得懒惰,而不是重新发明轮子。“试着懒惰,而不是重新发明轮子。”-有时你必须发明一个不同的轮子,以使其适合你的业务需求(你已经注意到Breeze.js轮子并不真正适合)。T4非常简单。我建议你使用有形T4编辑器。他们有一个免费版,它突出了“模板代码”与“生成的代码”不同。它真的很有用。我还推荐T4工具箱。我已经编写了几十个T4模板,但没有一个与您正在寻找的模板相关。您是否考虑过使用像Breeze.js这样的客户端数据库,这样您就不必在客户端和服务器上创建模型?Breeze的问题是它仍然不是强类型的。其全部目的是使所有内容都完全强类型化,因此任何地方的任何更改都将抛出编译时错误,而不是随机显示。通过使用t4 viewmodel生成器,即使您使用的是Breeze,您也可以对对象进行强强制转换,这样所有内容都可以在Typescript中进行强类型化。只是搞乱了它,它只是一个相当丑陋的文档,关于做一些简单的事情,比如循环类库中的所有内容并查找属性,然后我需要做一些事情,比如创建枚举,记住我已经创建了它们,处理继承等。试着变得懒惰,而不是重新发明轮子。“试着偷懒,而不是重新发明轮子。”-有时你必须发明一个不同的轮子,以使其适合你的业务需求(你已经注意到Breeze.js轮子并不真正适合)。T4非常简单。我建议你使用有形T4编辑器。他们有一个免费版,它突出了