模板方法
根据您的需要,我建议您使用模板而不是开发您的自定义生产者,其中包括部署原因。使用模板生成器(随 CodeFluent Entities 提供),您可以利用 CodeFluent Entities 元模型快速轻松地创建复杂的脚本。
该生产者基于 CodeFluent Entities 的模板引擎,允许您在生产时生成文本文件(在您的情况下为 JavaScript)。提醒一下,模板只是文本块和可以生成输出文件的控制逻辑的混合体
该生产者负责所有常见操作:更新项目 (.XXproj) 以添加您生成的文件、添加缺失的引用等。之后您可以找到一个示例以基于 CodeFluent 实体模型生成 IndexDB 脚本文件(仅用于演示目的) )。这是模板源文件:
[%@ reference name="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Core.dll" %]
[%@ namespace name="System" %]
[%@ namespace name="System.Linq" %]
[%@ namespace name="CodeFluent.Model" %]
var context = {};
context.indexedDB = {};
context.indexedDB.db = null;
context.indexedDB.open = function () {
var version = 11;
var request = indexedDB.open([%=Producer.Project.DefaultNamespace%], version);
request.onupgradeneeded = function (e) {
var db = e.target.result;
e.target.transaction.onerror = context.indexedDB.onerror;
[%foreach(Entity entity in Producer.Project.Entities){
string properties = String.Join(", ", entity.Properties.Where(p => !p.IsPersistenceIdentity).Select(p => "\"" + p.Name + "\""));
%]
if (db.objectStoreNames.contains("[%=entity.Name%]")) {
db.deleteObjectStore("[%=entity.Name%]");
}
var store = db.createObjectStore("[%=entity.Name%]",
{ keyPath: "id", autoIncrement: true });
store.createIndex([%=properties %], { unique: false });[%}%]
};
request.onsuccess = function (e) {
context.indexedDB.db = e.target.result;
};
request.onerror = context.indexedDB.onerror;
};
[%foreach(Entity entity in Producer.Project.Entities){
string parameters = String.Join(", ", entity.Properties.Where(p => !p.IsPersistenceIdentity).Select(p => p.Name));%]
context.indexedDB.[%=entity.Name%] = {}
context.indexedDB.[%=entity.Name%].add = function ([%= parameters %]) {
var db = context.indexedDB.db;
var trans = db.transaction(["[%=entity.Name%]"], "readwrite");
var store = trans.objectStore("[%=entity.Name%]");
var request = store.put({
[%
foreach (Property property in entity.Properties.Where(p => !p.IsPersistenceIdentity)) {%]
"[%=property.Name%]": [%=property.Name%], [%}%]
"timeStamp": new Date().getTime()
});
request.onsuccess = function (e) {
console.log(e.value);
};
request.onerror = function (e) {
console.log(e.value);
};
};
context.indexedDB.[%=entity.Name%].delete = function (id) {
var db = context.indexedDB.db;
var trans = db.transaction(["[%=entity.Name%]"], "readwrite");
var store = trans.objectStore("[%=entity.Name%]");
var request = store.delete(id);
request.onsuccess = function (e) {
console.log(e);
};
request.onerror = function (e) {
console.log(e);
};
};
context.indexedDB.[%=entity.Name%].loadAll = function () {
var db = context.indexedDB.db;
var trans = db.transaction(["[%=entity.Name%]"], "readwrite");
var store = trans.objectStore("[%=entity.Name%]");
var keyRange = IDBKeyRange.lowerBound(0);
var cursorRequest = store.openCursor(keyRange);
request.onsuccess = function (e) {
// not implemented
};
request.onerror = function (e) {
console.log(e);
};
};
[%}%]
function init() {
context.indexedDB.open(); // initialize the IndexDB context.
}
window.addEventListener("DOMContentLoaded", init, false);
然后您需要通过添加模板生成器来配置您的 CodeFluent 实体项目,并将上面的模板定义为源文件。
如果您考虑以下模型:
只需构建它以在目标项目(例如 Web 应用程序)中生成 IndexDB 脚本文件,您就可以像这样操作生成的 API:
context.indexedDB.Contact.add("Peter", "Boby")
context.indexedDB.Product.add("Tablet")
context.indexedDB.Product.add("Computer")
context.indexedDB.Contact.delete(1)
context.indexedDB.Product.loadAll()
自定义生产者方法
不过,如果您需要针对 CodeFluent 实体本身不支持的技术或平台,您可以通过实现 IProducer 接口来创建自己的自定义生产者:
public interface IProducer
{
event Producer.OnProductionEventHandler Production;
void Initialize(Project project, Producer producer);
void Produce();
void Terminate();
}
首先,您需要了解 CodeFluent Entitie Build 引擎会一一调用您配置的每个生产者来生成您的代码。
首先,CodeFluent EntitiesInitialize
为每个生产者调用该方法。它将 CodeFluent Entities 项目的实例和当前生产者作为参数。然后它Product
按照相同的过程调用该方法。这是实现您的生成逻辑的正确位置。最后,您可以在方法中实现终结逻辑Terminate
。
CodeFluent 提供了一些实现 IProducer 接口的基类,例如 BaseProducer,它位于 CodeFluent.Producers.CodeDom 程序集中,提供“添加缺失的引用”或“更新 Visual Studio 项目 (.XXproj) 等行为。
此外,这里有一篇博文可以帮助您将自定义生产者集成到建模器中。
子生产者方法
另一种方法可能是开发自定义 Sub-Producer,但在我看来,它不适合您的需求。