Code
window.addEventListener("DOMContentLoaded", () => {
const publicProps = /\bpublic\b.*?\s+?([_a-zA-Z0-9<>\[\]\?]+)\s+([_a-zA-Z0-9]+)[^\w]*/gm;
//const publicProps = /\bpublic\b.*?\s+?([_a-zA-Z0-9<>\[\]\?]+)\s+([_a-zA-Z0-9]+?)\s*[;{=]/gm;
const fallbackProps = /\b([_a-zA-Z0-9<>\[\]\?]+)\s+([_a-zA-Z0-9]+?)\s*[;{=]/gm;
const reClass = /\b(class|interface|struct)\s*?([^\s]+)/gi;
const reSingleLineComment = /(\/\/.*)/g;
const reMultiLineComment = /\/\*(.|[\r\n])*?\*\//gm;
const reEmptyOrBlankLines = /\n+\s*\n/gm;
let className = "Unknown";
let targetClass = "";
const tab = "\t";
const line = "\r\n";
const getMatches = (re, str) => {
let match, matches = [];
while (match = re.exec(str)) {
matches.push(match);
}
return matches;
};
const filterProps = (prop) => {
const reserved = ["void", "return", "class", "struct", "enum", "using", "var"];
return reserved.indexOf(prop.type) === -1;
};
const convertGetSet = (prop) => {
const p = prop.name;
return `public ${prop.type} ${p} { get; set; }`;
};
const convertInitializer = (prop, prefix) => {
const p = prop.name;
let c = prop.last ? "" : ",";
return `${p} = ${prefix}${p}${c}`; // ${prop.type}
};
const convertAssignment = (prop, prefix, prefix2) => {
const p = prop.name;
return `${prefix}${p} = ${prefix2}${p};`; // ${prop.type}
};
const mapTabs = (arr, tabCount) => {
const tabs = tab.repeat(tabCount);
return Array.from(arr).map(a => tabs + a);
}
const mapProps = (match, i, arr) => {
return { type: match[1], name: match[2], last: arr.length - 1 === i };
};
const convertAll = (str) => {
str = String(str).replace(reSingleLineComment, "");
str = String(str).replace(reMultiLineComment, "");
str = String(str).replace(reEmptyOrBlankLines, "\n");
console.log(str);
let props = getMatches(publicProps, str).map(mapProps).filter(filterProps);
if (props.length < 1) {
props = getMatches(fallbackProps, str).map(mapProps).filter(filterProps);
}
console.table(props);
console.log(JSON.stringify(props.reduce((x, p) => { x[p.name] = p.type; return x; }, {}), null, 4));
const props1 = mapTabs(props.map(p => convertGetSet(p)), 1);
const props2 = mapTabs(props.map(p => convertAssignment(p, "dest.", "src.")), 1);
const props3 = mapTabs(props.map(p => convertInitializer(p, "src.")), 2);
const props4 = mapTabs(props.map(p => convertAssignment(p, "", "src.")), 1);
const mapFrom = mapTabs([
`public static ${targetClass} FromDomain(${className} src, ${targetClass} dest = null) => FromDomainExt(src, dest);`,
`public static T FromDomainExt<T>(${className} src, T dest = null) where T: ${targetClass}, new()`,
`{`,
tab + `if (src == null) return null;`,
tab + `if (dest == null) dest = new T();`,
...props2,
tab + `return dest;`,
`}`
], 1);
const mapTo = mapTabs([
`public static ${className} ToDomain(${targetClass} src, ${className} dest = null) => ToDomainExt(src, dest);`,
`public static T ToDomainExt<T>(${targetClass} src, T dest = null) where T: ${className}, new()`,
`{`,
tab + `if (src == null) return null;`,
tab + `if (dest == null) dest = new T();`,
...props2,
tab + `return dest;`,
`}`
], 1);
// const mapCopyFrom = mapTabs([
// `public void CopyFrom(${className} src)`,
// `{`,
// ...props4,
// `}`
// ], 1);
// const mapCopyTo = mapTabs([
// `public static ${className} CopyTo(this ${className} src, ${targetClass} dest)`,
// `{`,
// ...props2,
// `}`
// ], 1);
const classMapper = mapTabs([
`public class ${targetClass}`,
`{`,
...props1,
"",
...mapFrom,
...mapTo,
// ...mapCopyFrom,
// ...mapCopyTo,
`}`
], 0);
const mapperClassSrc = classMapper.join(line);
const toDomainMapper = mapTabs([
`public static ${className} ToDomain(this ${targetClass} src)
{`,
`\tif (src == null) return null;`,
`\treturn new ${className}() {`,
...props3,
`\t};`,
`}`
], 1);
const fromDomainMapper = mapTabs([
`public static ${targetClass} FromDomain(this ${className} src)
{`,
`\tif (src == null) return null;`,
`\treturn new ${targetClass}() {`,
...props3,
`\t};`,
`}`
], 1);
const extensionMapperSrc = mapTabs([
`public static class ${targetClass}Extensions`,
`{`,
...toDomainMapper,
"",
...fromDomainMapper,
`}`
], 0).join(line);
const entityConfigure = mapTabs([
`public void Configure(EntityTypeBuilder<${targetClass}> entityTypeBuilder)`,
`{`,
`\tentityTypeBuilder.ToTable("${className}");`,
`\tentityTypeBuilder.HasKey(x => x.${props[0].name});`,
...props.map(p => `\tentityTypeBuilder.Property(x => x.${p.name});`),
`}`
], 1);
const entityMapperSrc = mapTabs([
`public class ${targetClass}Map : IEntityTypeConfiguration<${targetClass}>`,
`{`,
...entityConfigure,
`}`
], 0).join(line);
return [mapperClassSrc, extensionMapperSrc, entityMapperSrc].join("\n");
};
const run = () => {
const input = document.querySelector("#input").value;
className = (reClass.exec(input) || [])[2] || null;
if (className) {
targetClass = `Dm${className}`;
const output = convertAll(input);
document.querySelector("#output").value = output;
}
};
document.querySelector("#btnRun").addEventListener("click", run);
});159050cookie-checkC# Mapper