Created
May 19, 2012 23:37
-
-
Save anaisbetts/2732823 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/////////////// | |
// Type in this | |
/////////////// | |
interface IColorPicker : IRoutableViewModel { | |
int Red { get; set; } | |
int Green { get; set; } | |
int Blue { get; set; } | |
Color FinalColor { get; } | |
} | |
interface ILoginDialog : IRoutableViewModel { | |
[Once] | |
IAppState AppState { get; } | |
string User { get; set; } | |
string Password { get; set; } | |
string PasswordAgain { get; set; } | |
ReactiveCommand Ok { get; } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////////////////// | |
// | |
// And you get this as output: | |
// NB: Not *quite* this, but 99% of the way there! | |
////////////////// | |
using System; | |
using ReactiveUI; | |
using ReactiveUI.Xaml; | |
using ReactiveUI.Routing; | |
namespace TODOFillMeIn.ViewModels | |
{ | |
interface IColorPicker : IRoutableViewModel | |
{ | |
int Red { get; set; } | |
int Green { get; set; } | |
int Blue { get; set; } | |
Color FinalColor { get; } | |
} | |
interface ILoginDialog : IRoutableViewModel | |
{ | |
IAppState AppState { get; } | |
string User { get; set; } | |
string Password { get; set; } | |
string PasswordAgain { get; set; } | |
ReactiveCommand Ok { get; } | |
} | |
public void ColorPicker : ReactiveObject, IColorPicker | |
{ | |
int _Red; | |
public int Red { | |
get { return _Red; } | |
set { this.RaiseAndSetIfChanged(x => x.Red, value); } | |
} | |
int _Green; | |
public int Green { | |
get { return _Green; } | |
set { this.RaiseAndSetIfChanged(x => x.Green, value); } | |
} | |
int _Blue; | |
public int Blue { | |
get { return _Blue; } | |
set { this.RaiseAndSetIfChanged(x => x.Blue, value); } | |
} | |
ObservableAsPropertyHelper<Color> _FinalColor; | |
public Color FinalColor { | |
get { return _FinalColor; } | |
} | |
public IScreen HostScreen { get; protected set; } | |
public string UrlPathSegment { | |
get { return "TODO: Implement Me"; } | |
} | |
public ColorPicker(IScreen hostScreen) | |
{ | |
HostScreen = hostScreen; | |
// TODO: Wire up your properties here! | |
} | |
} | |
public void LoginDialog : ReactiveObject, ILoginDialog | |
{ | |
IAppState AppState { get; protected set; } | |
string _User; | |
public string User { | |
get { return _User; } | |
set { this.RaiseAndSetIfChanged(x => x.User, value); } | |
} | |
string _Password; | |
public string Password { | |
get { return _Password; } | |
set { this.RaiseAndSetIfChanged(x => x.Password, value); } | |
} | |
string _PasswordAgain; | |
public string PasswordAgain { | |
get { return _PasswordAgain; } | |
set { this.RaiseAndSetIfChanged(x => x.PasswordAgain, value); } | |
} | |
ReactiveCommand Ok { get; protected set; } | |
public IScreen HostScreen { get; protected set; } | |
public string UrlPathSegment { | |
get { return "TODO: Implement Me"; } | |
} | |
public LoginDialog(IScreen hostScreen) | |
{ | |
HostScreen = hostScreen; | |
AppState = null; // TODO: Set me | |
Ok = null; // TODO: Set me | |
// TODO: Wire up your properties here! | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using ReactiveUI; | |
using ReactiveUI.Xaml; | |
using ReactiveUI.Routing; | |
namespace TODOFillMeIn.ViewModels | |
{ | |
{{#interfaces}} | |
{{definition}} | |
{{/interfaces}} | |
{{#interfaces}} | |
public void {{implClassName}} : ReactiveObject, {{interfaceName}} | |
{ | |
{{#properties}} | |
{{#outputProp}} | |
ObservableAsPropertyHelper<{{type}}> _{{name}}; | |
public {{type}} {{name}} | |
{ | |
get { return _{{name}}; } | |
} | |
{{/outputProp}} | |
{{#readWriteProp}} | |
{{type}} _{{name}}; | |
public {{type}} {{name}} | |
{ | |
get { return _{{name}}; } | |
set { this.RaiseAndSetIfChanged(x => x.{{name}}, value); } | |
} | |
{{/readWriteProp}} | |
{{#onceProp}} | |
{{type}} {{name}} { get; protected set; } | |
{{/onceProp}} | |
{{#anythingElse}} | |
{{name}} | |
{{/anythingElse}} | |
{{/properties}} | |
{{#isRoutableViewModel}} | |
public IScreen HostScreen { get; protected set; } | |
public string UrlPathSegment { | |
get { return "TODO: Implement Me"; } | |
} | |
public {{implClassName}}(IScreen hostScreen) | |
{ | |
HostScreen = hostScreen; | |
{{#onceProperties}} | |
{{name}} = null; // TODO: Set me | |
{{/onceProperties}} | |
// TODO: Wire up your properties here! | |
} | |
{{/isRoutableViewModel}} | |
{{^isRoutableViewModel}} | |
public {{implClassName}}() | |
{ | |
{{#onceProperties}} | |
{{name}} = null; // TODO: Set me | |
{{/onceProperties}} | |
// TODO: Wire up your properties here! | |
} | |
{{/isRoutableViewModel}} | |
} | |
{{/interfaces}} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ViewModelRenderer : IEnableLogger | |
{ | |
public string RenderViewModel(string interfaceCode) | |
{ | |
var tree = SyntaxTree.ParseCompilationUnit(interfaceCode, "foo.cs"); | |
var root = tree.GetRoot(new CancellationToken()); | |
if (!root.ChildNodes().Any()) { | |
throw new ArgumentException("Compilation failed or code is badly formatted"); | |
} | |
if (!root.ChildNodes().All(x => x is InterfaceDeclarationSyntax)) { | |
throw new ArgumentException("Code must be one ore more interfaces"); | |
} | |
var renderInfo = root.ChildNodes() | |
.OfType<InterfaceDeclarationSyntax>() | |
.Select(renderInterface) | |
.ToArray(); | |
var template = File.ReadAllText(@"C:\Users\Administrator\Documents\GitHub\RxUIInterfaceToVM\Template.mustache"); | |
var ret = chompedString(Nustache.Core.Render.StringToString(template, new { interfaces = renderInfo })); | |
return ret; | |
} | |
InterfaceRenderInformation renderInterface(InterfaceDeclarationSyntax interfaceDecl) | |
{ | |
var ret = new InterfaceRenderInformation(); | |
ret.isRoutableViewModel = interfaceDecl.BaseListOpt.Types.Any(x => x.PlainName == "IRoutableViewModel") ? this : null; | |
ret.definition = chompedString(interfaceDecl.ToString().Replace("[Once]", "")); | |
ret.interfaceName = chompedString(interfaceDecl.Identifier.ValueText); | |
ret.implClassName = ret.interfaceName.Substring(1); // Skip the 'I' | |
var children = interfaceDecl.ChildNodes().Skip(1); | |
ret.properties = children.Select(renderPropertyDeclaration).ToArray(); | |
ret.onceProperties = ret.properties.Where(x => x.onceProp != null).Select(x => x.onceProp).ToArray(); | |
return ret; | |
} | |
PropertyRenderInformation renderPropertyDeclaration(SyntaxNode node) | |
{ | |
var propDecl = node as PropertyDeclarationSyntax; | |
if (propDecl == null) { | |
return new PropertyRenderInformation() { | |
anythingElse = new NameAndTypeRenderInformation() { name = chompedString(node.ToString()) }, | |
}; | |
} | |
var nameAndType = new NameAndTypeRenderInformation() { | |
name = chompedString(propDecl.Identifier.ValueText), | |
type = chompedString(propDecl.Type.PlainName), | |
}; | |
var commands = new[] { | |
"ReactiveCommand", | |
"ReactiveAsyncCommand", | |
}; | |
if (propDecl.Attributes.SelectMany(x => x.Attributes).Any(x => x.Name.PlainName == "Once") || | |
commands.Contains(propDecl.Type.PlainName)) { | |
return new PropertyRenderInformation() { onceProp = nameAndType, }; | |
} | |
if (propDecl.AccessorList.Accessors.Any(x => x.Keyword.Kind == SyntaxKind.SetKeyword)) { | |
return new PropertyRenderInformation() { readWriteProp = nameAndType, }; | |
} else { | |
return new PropertyRenderInformation() { outputProp = nameAndType, }; | |
} | |
} | |
string chompedString(string code) | |
{ | |
if (!code.Contains("\n")) { | |
return code.TrimEnd(' ', '\t'); | |
} | |
var lines = code.Split('\n') | |
.Select(x => x.TrimEnd(' ', '\t')) | |
.Where(x => !(String.IsNullOrWhiteSpace(x) && x.Length > 2)); | |
return String.Join("\n", lines); | |
} | |
} | |
public class InterfaceRenderInformation | |
{ | |
public IEnumerable<PropertyRenderInformation> properties { get; set; } | |
public string definition { get; set; } | |
public string implClassName { get; set; } | |
public string interfaceName { get; set; } | |
public object isRoutableViewModel { get; set; } // 'this' if true, null if false, Mustacheism | |
public IEnumerable<NameAndTypeRenderInformation> onceProperties { get; set; } | |
} | |
public class PropertyRenderInformation | |
{ | |
// NB: Only *one* of these should be non-null, Mustacheism | |
public NameAndTypeRenderInformation outputProp { get; set; } | |
public NameAndTypeRenderInformation onceProp { get; set; } | |
public NameAndTypeRenderInformation readWriteProp { get; set; } | |
public NameAndTypeRenderInformation anythingElse { get; set; } | |
} | |
public class NameAndTypeRenderInformation | |
{ | |
public string name { get; set; } | |
public string type { get; set; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment