diff --git a/src/ContextGenerator/BindingContextGenerator.Template.cs b/src/ContextGenerator/BindingContextGenerator.Template.cs
index 985417f..bc1079e 100644
--- a/src/ContextGenerator/BindingContextGenerator.Template.cs
+++ b/src/ContextGenerator/BindingContextGenerator.Template.cs
@@ -6,24 +6,21 @@
public partial class BindingContextGenerator
{
#region 类模板
- const string DefaultNamespace = "__DataBindingGenerated";
-
///
/// 构建绑定上下文
///
- public static string BuildContextCode(ContextBindingInfo contextInfo, string usings, string @namespace, string converters, string bindings, string unbindings, string functions)
+ public static string BuildContextCode(ContextBindingInfo contextInfo, string converters, string bindings, string unbindings, string functions)
{
return $$"""
{{Utility.FileHead}}
-{{usings}}
-namespace {{@namespace}}
+namespace {{Utility.BindingContextDefaultNamespace}}
{
[FUI.ViewModelAttribute(typeof({{contextInfo.viewModelType}}))]
[FUI.ViewAttribute("{{contextInfo.viewName}}")]
- public class __{{contextInfo.viewModelType.ToCSharpName()}}_{{contextInfo.viewName}}_Binding_Generated : FUI.BindingContext
+ public class {{contextInfo.viewModelType.ToCSharpName()}}_{{contextInfo.viewName}}_Binding_Generated : FUI.BindingContext
{
{{converters}}
- public __{{contextInfo.viewModelType.ToCSharpName()}}_{{contextInfo.viewName}}_Binding_Generated(FUI.IView view, FUI.Bindable.ObservableObject viewModel) : base(view, viewModel) { }
+ public {{contextInfo.viewModelType.ToCSharpName()}}_{{contextInfo.viewName}}_Binding_Generated(FUI.IView view, FUI.Bindable.ObservableObject viewModel) : base(view, viewModel) { }
protected override void Binding()
{
diff --git a/src/ContextGenerator/BindingContextGenerator.cs b/src/ContextGenerator/BindingContextGenerator.cs
index 913a03e..f261705 100644
--- a/src/ContextGenerator/BindingContextGenerator.cs
+++ b/src/ContextGenerator/BindingContextGenerator.cs
@@ -12,9 +12,6 @@ internal IReadOnlyList Generate(IReadOnlyList contex
var result = new List();
foreach (var bindingContext in contexts)
{
- var usings = new List(0);
- var @namespace = string.Empty;
-
var bindingBuilder = new StringBuilder();
var unbindingBuilder = new StringBuilder();
HashSet converterTypes = new HashSet();
@@ -65,15 +62,8 @@ internal IReadOnlyList Generate(IReadOnlyList contex
var convertersBuilder = new StringBuilder();
BuildConverterCostructor(converterTypes, ref convertersBuilder);
- //添加using
- var usingBuilder = new StringBuilder();
- BuildUsings(usings, ref usingBuilder);
-
- //添加Namespace
- var @namespaceName = string.IsNullOrEmpty(@namespace) ? DefaultNamespace : @namespace;
-
//组装所有的绑定代码
- var code = BuildContextCode(bindingContext, usingBuilder.ToString(), @namespaceName, convertersBuilder.ToString(), bindingBuilder.ToString(), unbindingBuilder.ToString(), functionBuilder.ToString());
+ var code = BuildContextCode(bindingContext, convertersBuilder.ToString(), bindingBuilder.ToString(), unbindingBuilder.ToString(), functionBuilder.ToString());
//格式化代码
code = Utility.NormalizeCode(code);
@@ -148,27 +138,6 @@ void BuildConverterCostructor(HashSet converterTypes, ref StringBuilder
}
}
- //构造所有的using
- void BuildUsings(IEnumerable usings, ref StringBuilder usingBuilder)
- {
- if (usings == null)
- {
- usingBuilder.AppendLine("");
- }
- else
- {
- foreach (var @using in usings)
- {
- if (string.IsNullOrEmpty(@using))
- {
- continue;
- }
-
- usingBuilder.AppendLine($"using {@using};");
- }
- }
- }
-
///
/// 生成从View到ViewModel的绑定代码和解绑代码
///
diff --git a/src/ContextInfoGenerator/ContextInfoByAttributeGenerator.cs b/src/ContextInfoGenerator/ContextInfoByAttributeGenerator.cs
index 732256f..2fa6a09 100644
--- a/src/ContextInfoGenerator/ContextInfoByAttributeGenerator.cs
+++ b/src/ContextInfoGenerator/ContextInfoByAttributeGenerator.cs
@@ -158,14 +158,13 @@ PropertyBindingInfo CreatePropertyBindingInfo(SemanticModel semanticModel, Class
PropertyInfo CreatePropertyInfo(SemanticModel semanticModel, ClassDeclarationSyntax clazz, PropertyDeclarationSyntax property, AttributeSyntax attribute)
{
var propertyName = property.Identifier.Text;
- var propertyType = semanticModel.GetTypeInfo(property).Type;
- var isList = Utility.IsObservableList(clazz, property);
+ var propertyType = semanticModel.GetTypeInfo(property.Type).Type;
return new PropertyInfo
{
name = propertyName,
type = propertyType.ToString(),
- isList = isList,
+ isList = propertyType.IsObservableList(),
location = property.GetLocation().ToLocationInfo(),
};
}
diff --git a/src/ContextInfoGenerator/ContextInfoByDescriptorGenerator.cs b/src/ContextInfoGenerator/ContextInfoByDescriptorGenerator.cs
index 520c215..aea5907 100644
--- a/src/ContextInfoGenerator/ContextInfoByDescriptorGenerator.cs
+++ b/src/ContextInfoGenerator/ContextInfoByDescriptorGenerator.cs
@@ -17,10 +17,6 @@ public List Generate(SemanticModel semanticModel, SyntaxNode
foreach (var classDeclaration in classDeclarations)
{
var classType = semanticModel.GetDeclaredSymbol(classDeclaration);
- if(classType.ToString() == "Test.Descriptor.TestDescriptorContextDescriptor")
- {
- var a = 0;
- }
if(!classType.IsContextDescriptor(out var viewModelType))
{
continue;
diff --git a/src/ContextInfoGenerator/ContextInfoGenerators.cs b/src/ContextInfoGenerator/ContextInfoGenerators.cs
index fa75c17..713bd31 100644
--- a/src/ContextInfoGenerator/ContextInfoGenerators.cs
+++ b/src/ContextInfoGenerator/ContextInfoGenerators.cs
@@ -76,7 +76,7 @@ internal async Task> Generate(Project project,
/// 输出文件夹
void TrySaveToFile(ContextBindingInfo info, string output)
{
- if (!string.IsNullOrEmpty(output))
+ if (string.IsNullOrEmpty(output))
{
return;
}
@@ -87,7 +87,8 @@ void TrySaveToFile(ContextBindingInfo info, string output)
}
var json = Newtonsoft.Json.JsonConvert.SerializeObject(info, Newtonsoft.Json.Formatting.Indented);
- var fileName = $"{Utility.GetBindingContextTypeName(info)}.binding";
+ //这个文件名要保持和上下文类型的全名一致 以便于后续根据上下文类型查找对应的绑定信息
+ var fileName = $"{Utility.GetBindingContextTypeFullName(info)}.binding";
var file = Path.Combine(output, fileName);
File.WriteAllText(file, json);
}
diff --git a/src/FUIStubs.cs b/src/FUIStubs.cs
index 9c76d52..6dd7260 100644
--- a/src/FUIStubs.cs
+++ b/src/FUIStubs.cs
@@ -7,6 +7,11 @@ public class CommandAttribute : Attribute { }
public interface IValueConverter { }
public interface IValueConverter { }
+
+ public interface ISynchronizeProperties
+ {
+ void Synchronize();
+ }
}
namespace FUI.BindingDescriptor
diff --git a/src/PipeServer/MessageClient.cs b/src/PipeServer/MessageClient.cs
new file mode 100644
index 0000000..8c3cce5
--- /dev/null
+++ b/src/PipeServer/MessageClient.cs
@@ -0,0 +1,179 @@
+using System.IO.Pipes;
+
+namespace FUICompiler
+{
+ internal class MessageClient : IDisposable
+ {
+ const string PipeName = "FUICompilerMessage";
+ const int BufferSize = 1024;
+ readonly NamedPipeClientStream pipeClient;
+ readonly Queue sendQueue = new Queue();
+ readonly CancellationTokenSource cts = new CancellationTokenSource();
+
+ public event Action MessageReceived;
+ public event Action Connected;
+ public event Action Disconnected;
+
+ static MessageClient instance;
+
+ public static MessageClient Instance
+ {
+ get
+ {
+ if (instance == null)
+ {
+ instance = new MessageClient();
+ }
+
+ return instance;
+ }
+ }
+
+ MessageClient()
+ {
+ pipeClient = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
+ }
+
+ public async Task ConnectAsync(int timeoutMs = 5000)
+ {
+ if (IsConnected)
+ {
+ return;
+ }
+
+ try
+ {
+ await pipeClient.ConnectAsync(timeoutMs, cts.Token);
+ Connected?.Invoke();
+
+ // 启动读写任务
+ _ = ReadMessagesAsync();
+ _ = ProcessSendQueueAsync();
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+
+ public void Send(byte[] bytes)
+ {
+ if (!IsConnected)
+ {
+ throw new InvalidOperationException("未连接到服务器");
+ }
+
+ lock (sendQueue)
+ {
+ sendQueue.Enqueue(bytes);
+ }
+ }
+
+ async Task ReadMessagesAsync()
+ {
+ var buffer = new byte[BufferSize];
+
+ try
+ {
+ while (IsConnected && !cts.Token.IsCancellationRequested)
+ {
+ var message = new List();
+ do
+ {
+ var bytesRead = await pipeClient.ReadAsync(buffer, 0, buffer.Length, cts.Token);
+ if (bytesRead == 0)
+ {
+ break;
+ }
+
+ for (int i = 0; i < bytesRead; i++)
+ {
+ message.Add(buffer[i]);
+ }
+ }
+ while (!pipeClient.IsMessageComplete);
+
+ MessageReceived?.Invoke(message.ToArray());
+ }
+ }
+ catch (IOException)
+ {
+ // 服务端断开连接
+ HandleDisconnection();
+ }
+ catch (OperationCanceledException)
+ {
+ // 正常取消
+ }
+ }
+
+ async Task ProcessSendQueueAsync()
+ {
+ try
+ {
+ while (IsConnected && !cts.Token.IsCancellationRequested)
+ {
+ byte[] message = null;
+
+ lock (sendQueue)
+ {
+ if (sendQueue.Count > 0)
+ {
+ message = sendQueue.Dequeue();
+ }
+ }
+
+ if (message != null)
+ {
+ await pipeClient.WriteAsync(message, 0, message.Length, cts.Token);
+ await pipeClient.FlushAsync(cts.Token);
+ }
+ else
+ {
+ await Task.Delay(100, cts.Token); // 避免空轮询
+ }
+ }
+ }
+ catch (IOException)
+ {
+ // 服务端断开连接
+ HandleDisconnection();
+ }
+ catch (OperationCanceledException)
+ {
+ // 正常取消
+ }
+ }
+
+ void HandleDisconnection()
+ {
+ if (!IsConnected)
+ {
+ return;
+ }
+
+ Disconnected?.Invoke();
+ }
+
+ public void Disconnect()
+ {
+ if (!IsConnected)
+ {
+ return;
+ }
+
+ cts.Cancel();
+ pipeClient.Close();
+ Disconnected?.Invoke();
+ }
+
+ public void Dispose()
+ {
+ Disconnect();
+ cts.Dispose();
+ pipeClient.Dispose();
+ }
+
+ public bool IsConnected => pipeClient.IsConnected;
+ }
+}
\ No newline at end of file
diff --git a/src/PipeServer/Server.cs b/src/PipeServer/Server.cs
deleted file mode 100644
index 9c5a0b0..0000000
--- a/src/PipeServer/Server.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System.IO.Pipes;
-using System.Security.Principal;
-
-namespace FUICompiler
-{
- internal class Server
- {
- void Start()
- {
- // 服务端
- using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut, 1))
- {
- Console.WriteLine("Named pipe server is running...");
- pipeServer.WaitForConnection();
- using (StreamWriter sw = new StreamWriter(pipeServer))
- {
- sw.WriteLine("Hello, client!");
- }
- }
-
- // 客户端
- using (NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.None))
- {
- pipeClient.Connect();
- using (StreamReader sr = new StreamReader(pipeClient))
- {
- Console.WriteLine(sr.ReadToEnd());
- }
- }
- }
- }
-}
diff --git a/src/Program.cs b/src/Program.cs
index 0d4a88f..19891da 100644
--- a/src/Program.cs
+++ b/src/Program.cs
@@ -11,8 +11,8 @@
try
{
- string workspace = "..\\..\\..\\..\\..\\..\\FUI\\";
- args = $"--sln={workspace}.\\FUI.sln --project=FUI.Test --output={workspace}.\\Library\\ScriptAssemblies --binding={workspace}.\\Binding\\ --generated={workspace}.\\FUI\\Generated\\ --ctx_type=Mix --binding_output={workspace}.\\FUI\\BindingInfo\\".Split(' ');
+ //string workspace = "..\\..\\..\\..\\..\\..\\FUI\\";
+ //args = $"--sln={workspace}.\\FUI.sln --project=FUI.Test --output={workspace}.\\Library\\ScriptAssemblies --binding={workspace}.\\Binding\\ --generated={workspace}.\\FUI\\Generated\\ --ctx_type=Mix --binding_output={workspace}.\\FUI\\BindingInfo\\".Split(' ');
var param = ParseArgs(args);
var compiler = new Compiler(param);
await compiler.Build();
diff --git a/src/PropertyDelegateGenerator/ObservableObjectDelegateGenerator.cs b/src/PropertyDelegateGenerator/ObservableObjectDelegateGenerator.cs
index c42605d..bd08cba 100644
--- a/src/PropertyDelegateGenerator/ObservableObjectDelegateGenerator.cs
+++ b/src/PropertyDelegateGenerator/ObservableObjectDelegateGenerator.cs
@@ -22,16 +22,16 @@ internal List Generate(SemanticModel semanticModel, SyntaxNode root)
var sources = new List();
foreach(var classDeclaration in classDeclarations)
{
- var type = semanticModel.GetDeclaredSymbol(classDeclaration);
+ var classType = semanticModel.GetDeclaredSymbol(classDeclaration);
//如果不是可观察对象直接不管
- if (!type.IsObservableObject())
+ if (!classType.IsObservableObject())
{
continue;
}
//如果是静态类或者抽象类直接不管
- if (type.IsAbstract || type.IsStatic)
+ if (classType.IsAbstract || classType.IsStatic)
{
continue;
}
@@ -51,7 +51,7 @@ internal List Generate(SemanticModel semanticModel, SyntaxNode root)
}
//判断是否有命名空间
- var @namespace = type.ContainingNamespace.ToDisplayString();
+ var @namespace = classType.ContainingNamespace.ToDisplayString();
var hasNamespace = !string.IsNullOrEmpty(@namespace);
if (hasNamespace)
{
@@ -60,7 +60,7 @@ internal List Generate(SemanticModel semanticModel, SyntaxNode root)
}
//生成分布类
- appendBuilder.AppendLine($"public partial class {type.Name} : {Utility.SynchronizePropertiesFullName}");
+ appendBuilder.AppendLine($"public partial class {classType.Name} : {typeof(FUI.ISynchronizeProperties).FullName}");
appendBuilder.AppendLine("{");
var syncPropertiesBuilder = new StringBuilder();
@@ -68,13 +68,10 @@ internal List Generate(SemanticModel semanticModel, SyntaxNode root)
//遍历所有属性 生成对应委托
foreach (var property in classDeclaration.ChildNodes().OfType())
{
- //if (!Utility.IsObservableProperty(classDeclaration, property))
- //{
- // continue;
- //}
+ var propertyTypeInfo = semanticModel.GetDeclaredSymbol(property);
- var propertyType = property.Type.ToString();
- var propertyName = property.Identifier.Text;
+ var propertyType = propertyTypeInfo.Type.ToString();
+ var propertyName = propertyTypeInfo.Name;
//生成BackingField
var fieldName = Utility.GetPropertyBackingFieldName(propertyName);
@@ -94,7 +91,7 @@ internal List Generate(SemanticModel semanticModel, SyntaxNode root)
var events = classDeclaration.DescendantNodes().OfType().ToArray();
foreach (var @event in events)
{
- var eventCaller = GenerateEventCaller(@event);
+ var eventCaller = GenerateEventCaller(semanticModel, @event);
appendBuilder.AppendLine(eventCaller);
}
@@ -107,7 +104,7 @@ internal List Generate(SemanticModel semanticModel, SyntaxNode root)
appendBuilder.AppendLine("}");
}
var code = Utility.NormalizeCode(appendBuilder.ToString());
- sources.Add(new Source($"{classDeclaration.Identifier.Text}.PropertyChanged.g", code));
+ sources.Add(new Source($"{classType.ToString()}.PropertyChanged.g", code));
}
return sources;
@@ -121,7 +118,7 @@ internal List Generate(SemanticModel semanticModel, SyntaxNode root)
void GenerateSyncPropertites(StringBuilder propertyDelegateBuilder, StringBuilder syncPropertiesBuilder)
{
//生成同步所有属性的方法
- propertyDelegateBuilder.AppendLine($"void {Utility.SynchronizePropertiesFullName}.{Utility.SynchronizePropertiesMethodName}()");
+ propertyDelegateBuilder.AppendLine($"void {typeof(FUI.ISynchronizeProperties).FullName}.{nameof(FUI.ISynchronizeProperties.Synchronize)}()");
propertyDelegateBuilder.AppendLine("{");
propertyDelegateBuilder.AppendLine(syncPropertiesBuilder.ToString());
propertyDelegateBuilder.AppendLine("}");
@@ -132,14 +129,28 @@ void GenerateSyncPropertites(StringBuilder propertyDelegateBuilder, StringBuilde
///
/// 事件字段
///
- string GenerateEventCaller(EventFieldDeclarationSyntax syntax)
+ string GenerateEventCaller(SemanticModel semanticModel, EventFieldDeclarationSyntax syntax)
{
- var argsType = (syntax.Declaration.Type as GenericNameSyntax).TypeArgumentList.Arguments;
+ var eventTypeInfo = semanticModel.GetTypeInfo(syntax.Declaration.Type);
+ var namedEventType = eventTypeInfo.Type as INamedTypeSymbol;
+ var argsTypesString = string.Empty;
+ var invokeParams = string.Empty;
+ if (namedEventType.IsGenericType)
+ {
+ var argsTypes = namedEventType.TypeArguments;
+ for(int i = 0; i< argsTypes.Length; i++)
+ {
+ var end = i == argsTypes.Length - 1 ? string.Empty : ",";
+ argsTypesString += $"{argsTypes[i]} arg{i}{end}";
+ invokeParams += $"arg{i}{end}";
+ }
+ }
+
var callerName = Utility.GetEventMethodName(syntax.Declaration.Variables.ToString());
return $$"""
-public void {{callerName}} ({{argsType}} args)
+public void {{callerName}} ({{argsTypesString}})
{
- this.{{syntax.Declaration.Variables}}?.Invoke(args);
+ this.{{syntax.Declaration.Variables}}?.Invoke({{invokeParams}});
}
""";
}
diff --git a/src/TypeSymbolExtensions.cs b/src/TypeSymbolExtensions.cs
index 0c26e22..edb8846 100644
--- a/src/TypeSymbolExtensions.cs
+++ b/src/TypeSymbolExtensions.cs
@@ -6,23 +6,55 @@ namespace FUICompiler
{
internal static class TypeSymbolExtensions
{
- public static bool Extends(this ITypeSymbol symbol, Type type)
+ static Queue cache = new Queue();
+
+ ///
+ /// 判断一个类型是否继承自某个类型或者实现了某个接口
+ ///
+ /// 源类型
+ /// 目标类型
+ ///
+ internal static bool Extends(this ITypeSymbol symbol, Type type)
{
if (symbol == null || type == null)
+ {
return false;
+ }
+
+ var openList = cache;
+ openList.Clear();
+ openList.Enqueue(symbol);
- while (symbol != null)
+ while(openList.Count > 0)
{
- if (symbol.Matches(type))
+ var current = openList.Dequeue();
+
+ if (current.Matches(type))
+ {
return true;
+ }
+
+ if (current.BaseType != null)
+ {
+ openList.Enqueue(current.BaseType);
+ }
- symbol = symbol.BaseType;
+ foreach (var @interface in current.Interfaces)
+ {
+ openList.Enqueue(@interface);
+ }
}
return false;
}
- public static bool Matches(this ITypeSymbol symbol, Type type)
+ ///
+ /// 判断一个类型是否和另一个类型匹配
+ ///
+ /// 源类型
+ /// 目标类型
+ ///
+ internal static bool Matches(this ITypeSymbol symbol, Type type)
{
switch (symbol.SpecialType)
{
@@ -42,23 +74,30 @@ public static bool Matches(this ITypeSymbol symbol, Type type)
}
if (!(symbol is INamedTypeSymbol named))
+ {
return false;
+ }
if (type.IsConstructedGenericType)
{
var args = type.GetTypeInfo().GenericTypeArguments;
if (args.Length != named.TypeArguments.Length)
+ {
return false;
+ }
for (var i = 0; i < args.Length; i++)
+ {
if (!Matches(named.TypeArguments[i], args[i]))
+ {
return false;
-
+ }
+ }
+
return Matches(named.ConstructedFrom, type.GetGenericTypeDefinition());
}
- return named.MetadataName == type.Name
- && named.ContainingNamespace?.ToDisplayString() == type.Namespace;
+ return named.MetadataName == type.Name && named.ContainingNamespace?.ToDisplayString() == type.Namespace;
}
///
@@ -70,15 +109,9 @@ public static bool Matches(this ITypeSymbol symbol, Type type)
internal static bool IsType(this ITypeSymbol symbol, Type type)
{
return Matches(symbol, type);
- if (!(symbol is INamedTypeSymbol named))
- {
- return false;
- }
-
- return named.Name == type.Name && named.ContainingNamespace?.ToDisplayString() == type.Namespace;
}
- public static IEnumerable GetBaseTypesAndThis(this ITypeSymbol type)
+ internal static IEnumerable GetBaseTypesAndThis(this ITypeSymbol type)
{
var current = type;
while (current != null)
@@ -88,7 +121,7 @@ public static IEnumerable GetBaseTypesAndThis(this ITypeSymbol type
}
}
- public static bool InheritsFromOrEquals(this ITypeSymbol type, ITypeSymbol baseType)
+ internal static bool InheritsFromOrEquals(this ITypeSymbol type, ITypeSymbol baseType)
{
foreach (var t in type.GetBaseTypesAndThis())
{
@@ -101,7 +134,7 @@ public static bool InheritsFromOrEquals(this ITypeSymbol type, ITypeSymbol baseT
return false;
}
- public static bool InheritsFrom(this ITypeSymbol type, Type baseType)
+ internal static bool InheritsFrom(this ITypeSymbol type, Type baseType)
{
foreach (var t in type.GetBaseTypesAndThis())
{
diff --git a/src/Utility.cs b/src/Utility.cs
index d18d80a..e720c05 100644
--- a/src/Utility.cs
+++ b/src/Utility.cs
@@ -6,11 +6,7 @@ namespace FUICompiler
{
public static class Utility
{
- public static string ObservableObjectFullName = "FUI.ObservableObjectAttribute";
- public static string ObservablePropertyFullName = "FUI.ObservablePropertyAttribute";
- public static string SynchronizePropertiesFullName = "FUI.ISynchronizeProperties";
- public static string SynchronizePropertiesMethodName = "Synchronize";
- public static string BindingConfigFullName = "FUI.BindingAttribute";
+ public const string BindingContextDefaultNamespace = "__DataBindingGenerated";
public static string FileHead = @"
//This file was generated by FUICompiler
@@ -74,162 +70,6 @@ public static string GetPropertyBackingFieldName(string propertyName)
return $"_{propertyName}_BackingField";
}
- ///
- /// 可观察对象基类类型名
- ///
- static string[] ObservableObjectBaseTypes = new string[]
- {
- "ObservableObject",
- "Bindable.ObservableObject",
- "FUI.Bindable.ObservableObject",
- "ViewModel",
- "FUI.ViewModel",
- };
-
- ///
- /// 可观察对象特性名
- ///
- static string[] ObservableObjectAttributes = new string[]
- {
- "ObservableObject",
- "FUI.ObservableObject",
- "ObservableObjectAttribute",
- "FUI.ObservableObjectAttribute",
-
- "Binding",
- "BindingAttribute",
- "FUI.Binding",
- "FUI.BindingAttribute"
- };
-
- ///
- /// 是否是可观察对象
- ///
- /// 类型定义
- ///
- public static bool IsObservableObject(ClassDeclarationSyntax classDeclaration)
- {
- //基类不为空
- if (classDeclaration.BaseList != null)
- {
- foreach (var baseType in classDeclaration.BaseList.Types)
- {
- if (ObservableObjectBaseTypes.Contains(baseType.Type.ToString()))
- {
- return true;
- }
- }
- };
-
- //特性不为空
- if (classDeclaration.AttributeLists != null)
- {
- foreach (var att in classDeclaration.AttributeLists)
- {
- foreach (var node in att.ChildNodes().OfType())
- {
- foreach (var id in node.ChildNodes().OfType())
- {
- if (ObservableObjectAttributes.Contains(id.ToString()))
- {
- return true;
- }
- }
- }
- }
- }
-
- return false;
- }
-
- ///
- /// 可绑定属性特性名
- ///
- static string[] ObservablePropertyAttributes = new string[]
- {
- "ObservableProperty",
- "ObservablePropertyAttribute",
- "FUI.ObservableProperty",
- "FUI.ObservablePropertyAttribute",
-
- "Binding",
- "BindingAttribute",
- "FUI.Binding",
- "FUI.BindingAttribute"
- };
-
- ///
- /// 可绑定属性忽略特性名
- ///
- static string[] ObservablePropertyIgnoreAttributes = new string[]
- {
- "ObservablePropertyIgnore",
- "ObservablePropertyIgnoreAttribute",
- "FUI.ObservablePropertyIgnore",
- "FUI.ObservablePropertyIgnoreAttribute"
- };
-
- ///
- /// 判断是一个属性是否是可观察属性
- ///
- ///
- ///
- ///
- public static bool IsObservableProperty(ClassDeclarationSyntax clazz, PropertyDeclarationSyntax propertyDeclaration)
- {
- if (!IsObservableObject(clazz))
- {
- return false;
- }
-
- var propertyAttributes = propertyDeclaration.AttributeLists.ToList();
- foreach (var att in propertyAttributes)
- {
- foreach (var node in att.ChildNodes().OfType())
- {
- foreach (var id in node.ChildNodes().OfType())
- {
- if (ObservablePropertyIgnoreAttributes.Contains(id.ToString()))
- {
- return false;
- }
- }
- }
- }
- return true;
- }
-
- ///
- /// 可绑定属性忽略特性名
- ///
- static string[] ObservableListTypeNames = new string[]
- {
- "ObservableList",
- "FUI.ObservableList",
- };
-
- ///
- /// 判断一个属性是否是可观察列表
- ///
- ///
- ///
- ///
- public static bool IsObservableList(ClassDeclarationSyntax clazz, PropertyDeclarationSyntax propertyDeclaration)
- {
- if (!IsObservableProperty(clazz, propertyDeclaration))
- {
- return false;
- }
-
- var propertyType = propertyDeclaration.Type;
- if (!(propertyType is GenericNameSyntax genericName))
- {
- return false;
- }
-
- return ObservableListTypeNames.Contains(genericName.Identifier.Text);
- }
-
///
/// 通过特性绑定的特性名
///
@@ -342,28 +182,6 @@ public static string GetEventMethodName(string eventName)
return $"__EventMethod_{eventName}";
}
- ///
- /// 尝试获取命名空间
- ///
- /// 类定义
- /// 命名空间名
- ///
- public static bool TryGetNamespace(ClassDeclarationSyntax classDeclaration, out string namespaceName)
- {
- namespaceName = null;
- var parent = classDeclaration.Parent;
- while (parent != null)
- {
- if (parent is NamespaceDeclarationSyntax namespaceDeclaration)
- {
- namespaceName = namespaceDeclaration.Name.ToString();
- return true;
- }
- parent = parent.Parent;
- }
- return false;
- }
-
///
/// 获取或者创建一个文件夹
///
@@ -384,7 +202,6 @@ public static DirectoryInfo GetOrCreateDirectory(string path)
///
/// 获取绑定上下文类型名
///
- /// 命名空间全称
/// 上下文信息
///
public static string GetBindingContextTypeName(ContextBindingInfo contextInfo)
@@ -392,6 +209,16 @@ public static string GetBindingContextTypeName(ContextBindingInfo contextInfo)
return $"{contextInfo.viewModelType.ToCSharpName()}_{contextInfo.viewName}_Binding_Generated";
}
+ ///
+ /// 获取绑定上下文类型全称
+ ///
+ /// 上下文信息
+ ///
+ public static string GetBindingContextTypeFullName(ContextBindingInfo contextInfo)
+ {
+ return $"{BindingContextDefaultNamespace}.{GetBindingContextTypeName(contextInfo)}";
+ }
+
///
/// 转换成位置信息
///