序文
長年コーダーとして、コーディングの効率を向上させる方法について考えてきました。
1、明確なプロジェクト構造で、一元的にコードを書くことができます。
2、少量のコードと明確かつ簡単に理解するのと同じ機能を達成するために
3.繰り返しまたは規則的なコードは自動的に生成されるべきです
ここではコード生成について説明します。
II.コードジェネレーターについて
私も新卒の頃はコードジェネレータにとても迷信を抱いていました。インターネット上でコードジェネレータや関連するソースコードを見つけるのが好きで、友人とどのジェネレータが***なのかを議論するのが好きでした:
1、生成されたコードは、あるべきコードではありません。
3は、基本的に生成されたエンティティクラスとSQLスプライシングコードは、現在直接linqまたはormのいくつかの良い使い方をより便利に、誰がまだSQLHelperプラスSQLテキストスプライシングを使用しますか?
4、b / sのプロジェクトは、ジェネレータを生成するために非常に良いことができます持っていないUIレイヤーのコードとjsコードのフロントエンドの相互作用は、生成することができる場合でも、また、単純なページです。
ですから、コード・ジェネレーターに夢中にならないよう、皆さんにアドバイスしたいと思います。効率は上がりますが、オンラインでジェネレーターを見つけることはできません。コードジェネレータはテンプレートエンジンに過ぎず、最も重要なのはコードジェネレータそのものではなく、関数やページコード指定の一種であり、独自のコードを洗練させ、共通のテンプレートを洗練させることです。
たとえば、一般的なクエリページ、エントリーページなど、限り、フォアグラウンドのHTML、フォアグラウンドのjs、バックグラウンドのコントローラ、バックグラウンドのデータサービスを含む標準的なクエリページのコードの洗練として。その後、テンプレートとして記述し、テンプレートエンジンを使用して必要なコードを生成することができます。
コードジェネレータ自体は、テンプレートエンジンですので、私は***コードジェネレータは、インターネット上で流通しているものは、3層アーキテクチャのコードソフトウェアを生成することはできませんが、Microsoftのカミソリエンジンは、非常にシンプルで理解しやすく、asp.net mvcのプロジェクトの友人を行っている非常に精通している必要がありますだと思います。私は個人的に、これはコード生成***エンジンを行うために使用されていると感じています。
III.ページテンプレート
例えば、いくつかの設定を選択し、htmlやjsを含む必要なコードを直接生成し、プロジェクトにコピーして直接実行することができ、見たいページの後に実行するなど、基本的な機能はありますが、それでも開発を高速化したいと思います。もちろん、ここで述べた迅速な開発は、私がテンプレートの上にページ機能を洗練させたことに基づいています。実際、私は3つのテンプレートを改良しました:
1.お照会ページ
このテンプレートは、お照会レポートのビジネス機能のほとんどを解決することができます。
2.ページの編集
それはマスターテーブル、および複数のスレーブテーブルのエントリが含まれているため、この編集テンプレートは、基本的にすべてのエントリ機能を解決することができます一度に同じトランザクションに保存することができます。そして、いくつかのビジネスプロセスを記述するために使用されるイベントの前後にトリガの多くを定義し、更新の違いを行うには。
3、クエリ編集ページでは、クエリもグリッドで直接編集することができ、このページには、いくつかの簡単なドキュメントまたはいくつかの基本的なデータのページを行うために使用されます。
コード生成の原則
上記のページコードをrazorテンプレートにし、razorテンプレート+セットオプション== razorエンジン==>ページコード
カミソリエンジンの使い方ですが、実はいくつか方法があります:
1、mvcのビュー出力関数の直接使用は、次のキーコード
var stringWriter = new StringWriter();
var viewContext = new ViewContext(controllerContext, view, viewData, TempData, stringWriter);
view.Render(viewContext, stringWriter);
var result = stringWriter.ToString();
このメソッドの利点は、サードパーティのライブラリを導入する必要がないことです、直接生成するRenderメソッドのmvcのビューを呼び出すと、非常に効率的な、欠点は、controllerContextとビューオブジェクトの構築は非常に複雑な取得することです。このメソッドは、クリーンコードファーマーに適用され、私はこの種に属しています。
2、サードパーティ製のクラスライブラリRazorEngineの出力の使用は、次のキーコード
var template = "Hello @Model.Name! Welcome to Razor!";
var viewData = new { Name = "World" });
var result = Razor.Parse(template, viewData);
このコードは、RazorEngineライブラリを導入しただけで、一見とても新鮮ですが、前者ほど効率的ではありません。
V. コード生成ユーザーインターフェース
テンプレートの準備が整い、エンジンの準備が整ったところで、データ入力用のviewDataが必要です。ユーザーインターフェースを作る目的は、このviewDataをより適切に定義することでもあります。
このユーザーインターフェースは、まだ3つのページ定義を分けなければなりません:
1、クエリーページ生成
***ステップは、コードカテゴリ検索(クエリページ)を選択し、データベースを選択し、ビジネスのメインテーブルを選択し、設定の部門のクエリ条件を達成するためにフィールドにチェックを入れて、ドラッグアンドドロップソート機能を実現します。あなたは、クエリに対してテンプレートを見ることができます。
ステップ 2: グリッドに表示する列を選択し、プロパティや書式などを設定します。
第3のステップは、主に以下のパラメータに基づいて、ネームスペースの決定、ファイル名の生成、その他の情報を含むいくつかのグローバル設定を行うことです。
ポップアップフォルダの生成後、設定に従ってコードを生成する[生成]ボタンをクリックすると、別途MVC 3層のコードが生成されています
mms_receive.cs
インデックス.cshtml
ReceiveController.cs
プロジェクトに直接このコードをコピーして直接実行すると、テスト条件付きフィルタリングは問題ありませんが、グリッドは、グリッドリモートのソートの高さに適応され、ページングページを選択しても問題ありませんが、すべての機能が利用可能です。
ルックアップ・コントロールだけがヌル値でポップアップします。なぜなら、コントロールはルックアップに設定されているだけで、それ以上の詳細なオプションは設定されていないからです。
つまり、コードジェネレータは、大規模な構造とUIを生成している、いくつかの小さな詳細または各コントロールのオプションも非常に複雑になる場合は、手動で生成されたコードのUIインターフェイスを変更するには、洗練する必要はありません。
2、編集ページ生成
***ステップは、フィールドとコントロールタイプのメインテーブルの編集領域を選択し、高度なコントロールタイプはまだ実装されていない、UIのこのエディタは、テンプレートのエディタを参照してくださいすることができます。
2番目のステップは、タブのタブを追加し、タブの種類を選択します(グリッド、フォーム、空)グリッドは、メインテーブルのN:1の関係を意味し、フォームはメインテーブルの1:1の関係を意味し、空のタブは、独自のコンテンツを追加することができます生成した後、空です。
ここでは、3 つのランダムなタブ tab1 tab2 tab3 を追加します。
tab1は、人事異動グリッド(メインテーブルとのN:1の関係)を置くために使用されます。
tab2はフォームを選択します(メインテーブルと1:1の関係、またはメインテーブルそのものを選択することもできます)。
そして、tab3のためのいくつかのランダムなもの。
ステップ3、その他の設定
生成ボタンをクリックすると、生成後に自動的にフォルダが開きます。
このコードをプロジェクトにコピーし、直接実行します。
タブ2
tab3は、メインテーブルデータを変更し、tab1、tab2、tab3ポイント保存、正常に保存することができます。
監査ボタンも利用可能ですが、監査後、ドキュメントは変更できません。
この編集機能は、基本的に多くのエントリーページを含むことができ、より一般的と考えることができます。
3、クエリー編集ページページ生成
***ステップでは、クエリ条件を選択し、コントロールタイプを設定します。
2番目のステップは、グリッドとエディタにデータ列を設定することです。
ステップ3、その他の設定
生成ボタンをクリックすると、生成後に自動的にフォルダが開きます。
実行するプロジェクトに直接コードをコピーし、結果は次のように、さらに設定する必要があるコントロールに加えて、テストした後、すべてのボタンが正常に使用される機能です!
#p#
VI.コード生成ページのソースコード
インデックス.cshtml
@{
ViewBag.Title = "コード生成";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@section head{
<link href="~/Content/js/jquery-plugins/smartwizard/smart_wizard.css" rel="stylesheet" />
<style type="text/css">
div#navigation{float: left;width: 180px;}
div#wrapper{float: right;width: 100%;margin-left: -185px;}
div#wizard{margin-left: 185px;}
ul.anchor{margin:0 0 10px 0 !important;}
ul li{margin-left:-16px;}
.grid .z-txt{margin:0 -3px;width:90%;}
.grid input{width:90%;}
.grid input[type=checkbox]{cursor:default;}
.grid select{width:80%;padding:0 !important;height:22px;}
.grid select + a{margin:5px;}
.tDnD_whileDrag{background-color: #FBEC88 !important;}
</style>
}
@section scripts{
<script src="~/Content/js/jquery-plugins/smartwizard/jquery.smartWizard.js"></script>
<script src="~/Content/js/jquery-extend/jquery.tablednd.js"></script>
@Scripts.Render("~/Resource/Sys/Generator.js")
<script type="text/javascript">
$(function () {
ko.applyBindings(new viewModel());
});
</script>
}
<div id="container">
<div id="navigation">
<div class="panel-header" style="width: 168px; border-width: 0; background: #FAFAFA;">
コードカテゴリー
<input type="text" class="z-txt" data-bind="easyuiCombobox:codetype" />
<div style="margin:1px;"></div>
データベース名
<input type="text" class="z-txt" data-bind="easyuiCombobox:database" />
<div style="margin:5px;"></div>
<div data-bind="autoheight:60" style="width: 172px; border-width: 0;margin:0;padding:0; background: #FAFAFA; overflow:auto;">
<ul data-bind="easyuiTree:tabletree"></ul>
</div>
</div>
</div>
<div id="wrapper">
<div id="wizard" class="swMain" style="width:100%"></div>
</div>
</div>
<script id="template-searchEdit" type="text/html">
<ul>
<li><a href="#step-1">
<label class="stepNumber">1</label>
<span class="stepDesc">条件セクションを設定する<br />
<small>クエリー条件を定義する</small>
</span>
</a></li>
<li><a href="#step-2">
<label class="stepNumber">2</label>
<span class="stepDesc">データ列を設定する<br />
<small>クエリに表示するデータフィールドを定義する</small>
</span>
</a></li>
<li><a href="#step-3">
<label class="stepNumber">3</label>
<span class="stepDesc">その他の設定<br />
<small>他のコード生成設定を変更する</small>
</span>
</a></li>
</ul>
<div id="step-1" class="step">
<h2 class="StepTitle">***步 请勾选要查询的 </h2>
<div>
<div style="width:200px;float:left;overflow:auto;" data-bind="autoheight:172">
<ul data-bind="easyuiTree:searchEdit.columntree"></ul>
</div>
<div style="float:left;overflow:auto" data-bind="autoheight:172,autowidth:405">
<table class="grid">
<thead>
<tr>
<th style="width:50px"> </th>
<th style="width:120px">表示名</th>
<th style="width:120px">コントロールタイプ</th>
@*<th > </th>*@
<th style="width:80px">クエリーロジック</th>
</tr>
</thead>
<tbody data-bind="foreach:form.conditions">
<tr data-bind="attr:{id:$index}">
<td data-bind="text:field" style="text-align:left"></td>
<td><input type="text" class="z-txt" data-bind="value:title"/></td>
<td><select class="z-txt" data-bind="options:$root.data.input,value:type"></select></td>
@*<td><input type="text" class="z-txt" data-bind="value:options"/></td>*@
<td><select class="z-txt" data-bind="options:$root.data.compare,value:cp"></select></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="step-2" class="step">
<h2 class="StepTitle">第二步 请勾选要显示的数据 </h2>
<div style="width:200px;float:left;overflow:auto;" data-bind="autoheight:172">
<ul data-bind="easyuiTree:searchEdit.columntree2"></ul>
</div>
<div style="float:left;overflow:auto" data-bind="autoheight:172,autowidth:405">
<table class="grid">
<thead>
<tr>
<th style="width:50px"> </th>
<th style="width:100px"> </th>
<th style="width:30px"> </th>
<th style="width:30px"> </th>
<th style="width:50px"> </th>
<th style="width:40px"> </th>
<th style="width:50px"> </th>
<th style="width:50px"> </th>
</tr>
</thead>
<tbody data-bind="foreach:form.columns">
<tr data-bind="attr:{id:$index}">
<td data-bind="text:field" style="text-align:left"></td>
<td><input type="text" class="z-txt" data-bind="value:title" /></td>
<td><input type="checkbox" data-bind="checked:hidden"/></td>
<td><input type="checkbox" data-bind="checked:sortable"/></td>
<td><select class="z-txt" data-bind="options:$root.data.align,value:align" ></select></td>
<td><input type="text" class="z-txt" data-bind="value:width" /></td>
<td><select class="z-txt" data-bind="options:$root.data.formatter,optionsText:'text',optionsValue:'value',value:formatter" ></select></td>
<td><select class="z-txt" data-bind="options:$root.data.editor,optionsText:'text',optionsValue:'value',value:editor" ></select></td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="step-3" class="step">
<h2 class="StepTitle">第三步 その他の設定</h2>
<div class="container_12">
<div class="grid_1 lbl">ビジネスエリア</div>
<div class="grid_2 val"><input type="text" class="z-txt" data-bind="value:form.area"/></div>
<div class="clear"></div>
<div class="grid_1 lbl">コントローラー名</div>
<div class="grid_2 val"><input type="text" class="z-txt" data-bind="value:form.controller"/></div>
<div class="clear"></div>
<div class="grid_1 lbl">パスを生成する</div>
<div class="grid_2 val"><input type="text" class="z-txt" data-bind="value:form.path"/></div>
</div>
</div>
</script>
<script id="template-search" type="text/html">
<ul>
<li><a href="#step-1">
<label class="stepNumber">1</label>
<span class="stepDesc">条件セクションを設定する<br />
<small>クエリー条件を定義する</small>
</span>
</a></li>
<li><a href="#step-2">
<label class="stepNumber">2</label>
<span class="stepDesc">データ列を設定する<br />
<small>クエリに表示するデータフィールドを定義する</small>
</span>
</a></li>
<li><a href="#step-3">
<label class="stepNumber">3</label>
<span class="stepDesc">その他の設定<br />
<small>他のコード生成設定を変更する</small>
</span>
</a></li>
</ul>
<div id="step-1" class="step">
<h2 class="StepTitle">***步 请勾选要查询的 </h2>
<div>
<div style="width:200px;float:left;overflow:auto;" data-bind="autoheight:172">
<ul data-bind="easyuiTree:searchEdit.columntree"></ul>
</div>
<div style="float:left;overflow:auto" data-bind="autoheight:172,autowidth:405">
<table class="grid">
<thead>
<tr>
<th style="width:50px"> </th>
<th style="width:120px">表示名</th>
<th style="width:120px">コントロールタイプ</th>
@*<th > </th>*@
<th style="width:80px">クエリーロジック</th>
</tr>
</thead>
<tbody data-bind="foreach:form.conditions">
<tr data-bind="attr:{id:$index}">
<td data-bind="text:field" style="text-align:left"></td>
<td><input type="text" class="z-txt" data-bind="value:title"/></td>
<td><select class="z-txt" data-bind="options:$root.data.input,value:type"></select></td>
@*<td><input type="text" class="z-txt" data-bind="value:options"/></td>*@
<td><select class="z-txt" data-bind="options:$root.data.compare,value:cp"></select></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="step-2" class="step">
<h2 class="StepTitle">第二步 请勾选要显示的数据字段</h2>
<div style="width:200px;float:left;overflow:auto;" data-bind="autoheight:172">
<ul data-bind="easyuiTree:searchEdit.columntree2"></ul>
</div>
<div style="float:left;overflow:auto" data-bind="autoheight:172,autowidth:405">
<table class="grid">
<thead>
<tr>
<th style="width:50px">字段</th>
<th style="width:100px"> </th>
<th style="width:30px"> </th>
<th style="width:30px"> </th>
<th style="width:50px"> </th>
<th style="width:40px"> </th>
<th style="width:50px"> </th>
</tr>
</thead>
<tbody data-bind="foreach:form.columns">
<tr data-bind="attr:{id:$index}">
<td data-bind="text:field" style="text-align:left"></td>
<td><input type="text" class="z-txt" data-bind="value:title" /></td>
<td><input type="checkbox" data-bind="checked:hidden"/></td>
<td><input type="checkbox" data-bind="checked:sortable"/></td>
<td><select class="z-txt" data-bind="options:$root.data.align,value:align" ></select></td>
<td><input type="text" class="z-txt" data-bind="value:width" /></td>
<td><select class="z-txt" data-bind="options:$root.data.formatter,optionsText:'text',optionsValue:'value',value:formatter" ></select></td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="step-3" class="step">
<h2 class="StepTitle">第三步 其它设置</h2>
<div class="container_12">
<div class="grid_1 lbl">ビジネスエリア</div>
<div class="grid_2 val"><input type="text" class="z-txt" data-bind="value:form.area"/></div>
<div class="clear"></div>
<div class="grid_1 lbl">コントローラー名</div>
<div class="grid_2 val"><input type="text" class="z-txt" data-bind="value:form.controller"/></div>
<div class="clear"></div>
<div class="grid_1 lbl">パスを生成する</div>
<div class="grid_2 val"><input type="text" class="z-txt" data-bind="value:form.path"/></div>
</div>
</div>
</script>
<script id="template-edit" type="text/html">
<ul>
<li><a href="#step-1">
<label class="stepNumber">1</label>
<span class="stepDesc">メインテーブルの編集エリアを設定する<br />
<small>メインテーブルの編集フィールドを定義する</small>
</span>
</a></li>
<li><a href="#step-2">
<label class="stepNumber">2</label>
<span class="stepDesc">詳細データタブを設定する<br />
<small>詳細テーブルとタブを定義する</small>
</span>
</a></li>
<li><a href="#step-3">
<label class="stepNumber">3</label>
<span class="stepDesc">其它设置<br />
<small>他のコード生成設定を変更する</small>
</span>
</a></li>
</ul>
<div id="step-1" class="step">
<h2 class="StepTitle">***步 请勾选要编辑的字段</h2>
<div>
<div style="width:200px;float:left;overflow:auto;" data-bind="autoheight:172">
<ul data-bind="easyuiTree:searchEdit.columntree"></ul>
</div>
<div style="float:left;overflow:auto" data-bind="autoheight:172,autowidth:405">
<table class="grid">
<thead>
<tr>
<th style="width:20%">字段</th>
<th style="width:40%">タグ名</th>
<th style="width:30%">コントロールタイプ</th>
<th style="width:10%"> </th>
</tr>
</thead>
<tbody data-bind="foreach:form.conditions">
<tr data-bind="attr:{id:$index}">
<td data-bind="text:field" style="text-align:left"></td>
<td><input type="text" class="z-txt" data-bind="value:title"/></td>
<td><select class="z-txt" data-bind="options:$root.data.input,value:type" style="width:60%"></select><a href="#"> </a></td>
<td><input type="checkbox" data-bind="checked:readonly"/></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="step-2" class="step">
<h2 class="StepTitle">第二步 请设置页面中的tab页签</h2>
<div style="float:left;overflow:auto;width:150px;" data-bind="autoheight:172">
<a href="#" class="buttonNext" style="float:left;margin:5px 3px 5px 0" data-bind="click:edit.addTab">タブを追加する</a>
<table class="grid">
<thead>
<tr>
<th style="width:30%">#</th>
<th style="width:70%"> </th>
</tr>
</thead>
<tbody data-bind="foreach:form.tabs">
<tr data-bind="attr:{id:$index}">
<td><a href="#" data-bind="click:$parent.edit.removeTab"> </a></td>
<td><input type="text" class="z-txt" data-bind="value:title,click:$parent.edit.clickTab" style="width:90%"/></td>
</tr>
</tbody>
</table>
</div>
<div id="edit-tab-setting" style="float:left;overflow:auto;" data-bind="autoheight:172,autowidth:355,visible:edit.selectedTitle()!=null">
</div>
</div>
<div id="step-3" class="step">
<h2 class="StepTitle">第三步 其它设置</h2>
<div class="container_12">
<div class="grid_1 lbl">ビジネスエリア</div>
<div class="grid_2 val"><input type="text" class="z-txt" data-bind="value:form.area"/></div>
<div class="clear"></div>
<div class="grid_1 lbl">コントローラー名</div>
<div class="grid_2 val"><input type="text" class="z-txt" data-bind="value:form.controller"/></div>
<div class="clear"></div>
<div class="grid_1 lbl">パスを生成する</div>
<div class="grid_2 val"><input type="text" class="z-txt" data-bind="value:form.path"/></div>
</div>
</div>
</script>
<script type="text/html" id="template-edit-tab-setting">
<div style="padding:8px;clear:both">
<span>ページタイプ </span>
<select class="z-txt" style="padding:0;height:22px;" data-bind="value:edit.selectedTab.type">
<option value="empty">empty</option>
<option value="grid">grid</option>
<option value="form">form</option>
</select>
<span data-bind="visible:edit.selectedTab.type()!='empty'"> データシート </span>
<select class="z-txt" style="padding:0;height:22px;" data-bind="options:data.table,optionsText:'text',optionsValue:'id',value:edit.selectedTab.subtable,visible:edit.selectedTab.type()!='empty'"></select>
<span data-bind="visible:edit.selectedTab.type()!='empty'">メインテーブルとの関連</span>
<select class="z-txt" style="padding:0;height:22px;" data-bind="options:data.tablekey,value:edit.selectedTab.relationship,visible:edit.selectedTab.type()!='empty'"></select>
</div>
<div style="width:180px;float:left;overflow:auto;margin-right:-18px;" data-bind="autoheight:212,visible:edit.selectedTab.type()!='empty'">
<ul data-bind="easyuiTree:edit.columntree2"></ul>
</div>
<div style="float:right;overflow:auto;" data-bind="autoheight:210,autowidth:535,visible:edit.selectedTab.type()!='empty'">
<table class="grid">
<thead>
<tr>
<th style="width:50px">字段</th>
<th style="width:100px"> </th>
<th style="width:30px" data-bind="visible:edit.selectedTab.type()=='grid'"> </th>
<th style="width:30px" data-bind="visible:edit.selectedTab.type()=='grid'"> </th>
<th style="width:50px" data-bind="visible:edit.selectedTab.type()=='grid'"> </th>
<th style="width:40px" data-bind="visible:edit.selectedTab.type()=='grid'"> </th>
<th style="width:50px" data-bind="visible:edit.selectedTab.type()=='grid'"> </th>
<th style="width:50px" data-bind="visible:edit.selectedTab.type()=='grid'"> </th>
<th style="width:50px" data-bind="visible:edit.selectedTab.type()=='form'">コントロールタイプ</th>
<th style="width:10px" data-bind="visible:edit.selectedTab.type()=='form'"> </th>
</tr>
</thead>
<tbody data-bind="foreach:edit.selectedTab.columns">
<tr data-bind="attr:{id:$index}">
<td data-bind="text:field" style="text-align:left"></td>
<td><input type="text" class="z-txt" data-bind="value:title" /></td>
<td data-bind="visible:$parent.edit.selectedTab.type()=='grid'"><input type="checkbox" data-bind="checked:hidden"/></td>
<td data-bind="visible:$parent.edit.selectedTab.type()=='grid'"><input type="checkbox" data-bind="checked:sortable"/></td>
<td data-bind="visible:$parent.edit.selectedTab.type()=='grid'"><select class="z-txt" data-bind="options:$root.data.align,value:align" ></select></td>
<td data-bind="visible:$parent.edit.selectedTab.type()=='grid'"><input type="text" class="z-txt" data-bind="value:width" /></td>
<td data-bind="visible:$parent.edit.selectedTab.type()=='grid'"><select class="z-txt" data-bind="options:$root.data.formatter,optionsText:'text',optionsValue:'value',value:formatter" ></select></td>
<td data-bind="visible:$parent.edit.selectedTab.type()=='grid'"><select class="z-txt" data-bind="options:$root.data.editor,optionsText:'text',optionsValue:'value',value:editor" ></select></td>
<td data-bind="visible:$parent.edit.selectedTab.type()=='form'"><select class="z-txt" data-bind="options:$root.data.input,value:type"></select></td>
<td data-bind="visible:$parent.edit.selectedTab.type()=='form'"><input type="checkbox" data-bind="checked:readonly"/></td>
</tr>
</tbody>
</table>
</div>
</script>
ジェネレータ
/**
* 模块名:mms viewModel
* : Generator.js
* (c) 2013 liuhuisheng [ liuhuisheng.xm@gmail.com ]
**/
var viewModel = function () {
var self = this;
this.form = {
type: '',
database:ko.observable(),
table: ko.observable(),
controller: ko.observable(),
area:ko.observable(),
conditions: ko.observableArray(),
columns: ko.observableArray(),
tabs: ko.observableArray(),
path: ko.observable("~/Generator/")
};
this.resetForm = function () {
self.form.conditions([]);
self.form.columns([]);
self.form.tabs([]);
};
this.data = {
codetype: [{ text: 'search', value: 'search' }, { text: 'edit', value: 'edit' }, { text: 'searchEdit', value: 'searchEdit' }],
database: ko.observableArray(),
table: ko.observableArray(),
column:ko.observableArray(),
tablekey: ko.observableArray(),
input: ['text', 'autocomplete', 'combobox', 'lookup','datebox','daterange'],
compare: ['equal', 'like', 'startwith', 'endwith', 'greater', 'less', 'daterange'],
align:['left','center','right'],
formatter: [{text:'',value:''},{ text: '', value: 'com.formatDate' }, { text: ' , value: 'com.formatTime' }, { text: ' , value: 'com.formatMoney' }, { text: ' , value: 'com.formatCheckbox' }],
editor: [{text:'',value:''},{ text: ' , value: 'text'}, { text: '整数', value: "{type: 'numberbox',options:{min: 0}}" }, { text: '小数点2桁の, value: "{type: 'numberbox',options:{min: 0, precision: 2}}" }, { text: 'ドロップダウンボックス, value: "{type:'combobox',options:{}}" }, { text: 'ポップアップボックス, value: "{type:'lookup',options:{}}" }, { text: '', value: 'datebox' }]
};
this.initDatabase = function () {
com.ajax({
type: 'GET',
async:false,
url: '/api/sys/generator/GetConnectionStrings',
success: function (d) {
self.data.database(d);
}
});
};
this.initDatabase();
this.getTableUrl = function () {
return '/api/sys/generator/GetTables?database=' + self.form.database();
};
this.getColumnUrl = function (table) {
return '/api/sys/generator/GetColumns?database=' + self.form.database() + "&table=" + table;
}
this.codetype = {
showblank: true,
width: 110,
data: self.data.codetype,
onSelect: function (node) {
self.form.type = node.value;
self.initWizard();
}
};
this.database = {
showblank: true,
width: 110,
data: self.data.database,
onSelect: function (node) {
self.form.database(node.value)
self.form.area((node.value.split('.')[1] || node.value).replace(/(^|\s+)\w/g, function (s) { return s.toUpperCase(); }));
}
};
this.tabletree = {
method: 'GET',
url: ko.computed(self.getTableUrl),
loadFilter: function (d) {
var data = utils.filterProperties(d.rows || d, ['TableName as id', 'TableName as text']);
self.data.table(data);
return data;
},
onSelect: function (node) {
self.form.table(node.id);
self.edit.init();
self.resetWizard();
self.form.controller((node.id.split('_')[1] || node.id).replace(/(^|\s+)\w/g, function (s) { return s.toUpperCase(); }));
}
};
this.generator = function () {
com.ajax({
type:'POST',
url: '/api/sys/generator',
data: ko.toJSON(self.form),
success: function (d) {
com.message('success', "コードが生成された!");
}
});
};
this.searchEdit = {};
this.searchEdit.columntree = {
method: 'GET',
url: ko.computed(function () {
return self.getColumnUrl(self.form.table());
}),
checkbox: true,
loadFilter: function (d) {
return utils.filterProperties(d.rows || d, ['ColumnName as id', 'ColumnName as text']);
},
onSelect: function (node) {
var handle = node.checked ? 'uncheck' : 'check';
$(this).tree(handle, node.target);
},
onCheck: function (node, checked) {
if (checked)
self.form.conditions.push({ field: node.id, title: node.id, type: 'text', options: '', cp: 'equal',readonly:false });
else
self.form.conditions.remove(function (item) { return item.field == node.id });
},
onLoadSuccess: self.resetForm
};
this.searchEdit.columntree2 = {
method: 'GET',
url: ko.computed(function () {
return self.getColumnUrl(self.form.table());
}),
checkbox: true,
loadFilter: function (d) {
return utils.filterProperties(d.rows || d, ['ColumnName as id', 'ColumnName as text']);
},
onSelect: function (node) {
var handle = node.checked ? 'uncheck' : 'check';
$(this).tree(handle, node.target);
},
onCheck: function (node, checked) {
var arr = self.form.columns;
if (checked) {
var item = $.grep(arr(), function (row) {return row.field == node.id;})[0];
item || arr.push({ field: node.id, title: node.id, hidden: false, sortable: true, align: 'left', width: 80, formatter: '', editor: 'text' });
} else
arr.remove(function (item) { return item.field == node.id });
}
};
this.edit = {};
this.edit.selectedTab = {
title: ko.observable(),
type: ko.observable(),
subtable: ko.observable(),
relationship: ko.observable(),
columns: ko.observableArray(),
primaryKeys:ko.observableArray()
};
this.edit.columntree2 = {
method: 'GET',
url:ko.observable(),
checkbox: true,
loadFilter: function (d) {
self.data.column(d);
var list = utils.filterProperties(d.rows || d, ['ColumnName as id', 'ColumnName as text']);
self.edit.setDefaultForm();
self.edit.resetTableKey();
var checkedList = [];
for (var i in self.edit.selectedTab.columns())
checkedList.push(self.edit.selectedTab.columns()[i].field);
for (var i in list)
if ($.inArray(list[i].id, checkedList) > -1) list[i].checked = true;
return list
},
onSelect: function (node) {
var handle = node.checked ? 'uncheck' : 'check';
$(this).tree(handle, node.target);
},
onCheck: function (node, checked) {
var arr = self.edit.selectedTab.columns;
if (checked) {
var item = $.grep(arr(), function (row) { return row.field == node.id; })[0];
item || arr.push({ field: node.id, title: node.id, hidden: false, sortable: true, align: 'left', width: 80, formatter: '', editor: 'text', type: '', readonly: true });
} else
arr.remove(function (item) { return item.field == node.id });
}
}
this.edit.init = function () {
self.edit.selectedTitle(null);
self.edit.selectedTab = null;
$('#edit-tab-setting').empty();
};
this.edit.addTab = function () {
var title = 'tab' + (self.form.tabs().length + 1);
var newTab = {
title: ko.observable(title),
type: ko.observable('empty'),
subtable: ko.observable(self.form.table()),
relationship: ko.observable(),
columns: ko.observableArray(),
primaryKeys:ko.observableArray()
};
newTab.type.subscribe(function (value) {
if (value == 'grid') {
var item = $.grep(self.data.table(), function (row) { return row.id == self.form.table() + "Detail" })[0];
if (item)
newTab.subtable(item.id);
}
else if (value == 'form') {
newTab.subtable(self.form.table());
}
});
newTab.columns.subscribe(self.tableDnDUpdate);
newTab.subtable.subscribe(function (value) {
self.edit.selectedTab.columns([]);
self.edit.columntree2.url(self.getColumnUrl(value));
});
self.form.tabs.push(newTab);
};
this.edit.removeTab = function (row,event) {
self.form.tabs.remove(row);
if (row.title() == self.edit.selectedTitle())
self.edit.selectedTitle(null);
};
this.edit.selectedTitle = ko.observable();
this.edit.clickTab = function (row, event) {
if (row.title() == self.edit.selectedTitle()) return;
self.edit.selectedTitle(row.title());
self.edit.selectedTab = row;
self.edit.columntree2.url = ko.observable(self.getColumnUrl(self.edit.selectedTab.subtable()));
var currentTr = $(event.srcElement).parent("td").parent("tr");
currentTr.parent().find("tr.tree-node-selected").removeClass("tree-node-selected");
currentTr.addClass("tree-node-selected");
var tabTemplate = $('#template-edit-tab-setting').html();
var wrapper = $('#edit-tab-setting').empty().html(tabTemplate);
ko.cleanNode(wrapper[0]);
ko.applyBindings(self, wrapper[0]);
wrapper.find("table").tableDnD({ onDrop: self.tableDnDSort });
};
this.edit.resetTableKey = function () {
var relationship = self.edit.selectedTab.relationship();
self.data.tablekey([]);
var cols = self.data.column();
for (var i in cols)
if (cols[i].IsIdentity || cols[i].IsPrimaryKey)
self.data.tablekey.push(cols[i].ColumnName);
self.edit.selectedTab.relationship(relationship);
self.edit.selectedTab.primaryKeys(self.data.tablekey());
};
this.edit.setDefaultForm = function () {
var arr = [
{ field: 'ApproveState', title: '承認状況, type: 'text', readonly: true },
{ field: 'ApproveRemark', title: '承認コメントの, type: 'text', readonly: true },
{ field: 'ApprovePerson', title: '承認者, type: 'text', readonly: true },
{ field: 'ApproveDate', title: '承認日, type: 'datebox', readonly: true },
{ field: 'CreatePerson', title: 'コンパイラの, type: 'text', readonly: true },
{ field: 'CreateDate', title: '準備日, type: 'datebox', readonly: true },
{ field: 'UpdatePerson', title: '修正者, type: 'text', readonly: true },
{ field: 'UpdateDate', title: '日付を変更する, type: 'datebox', readonly: true }
];
var cols = self.data.column();
var defaults = { field: '', title: '', hidden: false, sortable: true, align: 'left', width: 80, formatter: '', editor: 'text', type: '', readonly: true };
for (var i in arr) {
if (!$.grep(cols, function (item) { return item.ColumnName == arr[i].field; }).length)
return;
arr[i] = $.extend({}, defaults, arr[i]);
}
self.edit.selectedTab.columns(arr);
var tree = self.edit.columntree2.$element();
for (var i in arr) {
var node = tree.tree('find', arr[i].field);
if (node) tree.tree('check', node.target);
}
};
this.initWizard = function () {
var stepTemplate = $('#template-' + self.form.type);
if (!stepTemplate.length) return;
var wizard = $('#wizard').removeData('smartWizard').empty();
ko.cleanNode(wizard[0]);
wizard.html(stepTemplate.html());
wizard.smartWizard({
labelNext: '次のステップ,
labelPrevious: '前のステップ,
labelFinish: ' ,
onFinish: self.generator
});
var resizeStep = function () {
$(".step").height($(window).height() - 145)
.width($(window).width() - 205);
$(".actionBar").width($(window).width() - 195);
var index = wizard.smartWizard('currentStep');
wizard.smartWizard('goToStep', index);
};
$(window).resize(resizeStep);
resizeStep();
ko.applyBindings(self, wizard[0]);
wizard.find("table").tableDnD({ onDrop: self.tableDnDSort });
for (var i in self.form) {
if ($.isFunction(self.form[i]))
if (self.form[i]() instanceof Array)
if (self.form[i].subscribe)
self.form[i].subscribe(self.tableDnDUpdate);
}
};
this.resetWizard = function () {
var wizard = $("#wizard").smartWizard('goToStep', 1);
for (var i = 1; i <= wizard.find(">ul>li").length; i++)
wizard.smartWizard("disableStep", i);
};
this.tableDnDUpdate = function () {
setTimeout('$("table").tableDnDUpdate()', 300);
};
this.tableDnDSort = function (table, row) {
var name = $(table).find("tbody").attr("data-bind").replace('foreach:form.','');
var array = self.form[name], i = 0;
if (name == 'foreach:edit.selectedTab.columns')
array = self.edit.selectedTab.columns;
$("tr[id]", table).each(function () { array()[this.id].id = i++; });
array.sort(function (left, right) { return left.id == right.id ? 0 : (left.id < right.id ? -1 : 1) });
//for fix ko bug refresh ui
var tempArr = array();
array([]);
array(tempArr);
};
};
カミソリテンプレート
model.cshtml
@using Zephyr.Core.Generator
using System;
using System.Collections.Generic;
using System.Text;
using Zephyr.Core;
namespace Zephyr.Web.@(@Model.Area).Models
{
[Module("@Model.Database")]
public class @(Model.TableName)Service : ServiceBase<@Model.TableName>
{
}
public class @Model.TableName : ModelBase
{
@foreach(TableSchema item in Model.Columns)
{
if (item.IsIdentity)
{
@:[Identity]
}
if (item.IsPrimaryKey)
{
@:[PrimaryKey]
}
@:public @item.TypeName @item.ColumnName { get; set; }
}
}
}
テンプレートの他のページは、私は一つずつ投稿されません、あなたは共通のviewModel、クエリで私の以前のブログを見ることができますし、私が詳細に説明したページを編集し、また、テンプレートの独自のセットを絞り込むことができ、その後、コードジェネレータを作るために、この同じアイデアを使用することができます。
その後の発言
このコード生成機能を使えば、5分で基本的なページを作ることは全く問題ありません。
私はここで私自身のコード生成のアイデアを共有し、翡翠を誘致するためのレンガとして、我々はメッセージを残して歓迎するより良い方法を持っています。





