зеркало из https://github.com/wieslawsoltes/SVG.git
Refactoring of the Source Code Generator (#1141)
* Refactoring of the Source Code Generator - Moved the Svg_Model.cs file as SvgModel.cs into the main source. - Restore the standard naming of the generated code files with "*.g.cs" suffix. - Set the output directory of the generated codes to "Generated". - Added the Generated directory to the main source codes. - Moved the Svg.Custom project to Tests directory. * Update runtests.yml - NuGet/setup-nuget@v1 to NuGet/setup-nuget@v2 - Needed to eliminate the warning: Node.js 16 actions are deprecated. * Update AvailableElementsGenerator.cs Removed the comment out portions.
This commit is contained in:
Родитель
02518c43c1
Коммит
a2c69b70a1
|
@ -22,7 +22,7 @@ jobs:
|
|||
with:
|
||||
fetch-depth: 0 # needed for GitVersioning to work
|
||||
- name: Setup NuGet
|
||||
uses: NuGet/setup-nuget@v1
|
||||
uses: NuGet/setup-nuget@v2
|
||||
- name: Cache NuGet packages
|
||||
uses: actions/cache@v4
|
||||
id: cache
|
||||
|
@ -61,7 +61,7 @@ jobs:
|
|||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup NuGet
|
||||
uses: NuGet/setup-nuget@v1
|
||||
uses: NuGet/setup-nuget@v2
|
||||
- name: Cache NuGet packages
|
||||
uses: actions/cache@v4
|
||||
id: cache
|
||||
|
|
|
@ -361,3 +361,5 @@ Tests/W3CTestSuite/images
|
|||
Tests/W3CTestSuite/png
|
||||
Tests/W3CTestSuite/resources
|
||||
Tests/W3CTestSuite/svg
|
||||
|
||||
Source/Generated/**/*.cs
|
||||
|
|
|
@ -5,7 +5,6 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
namespace Svg.Generators
|
||||
|
@ -26,78 +25,6 @@ namespace Svg.Generators
|
|||
DiagnosticSeverity.Error,
|
||||
isEnabledByDefault: true);
|
||||
|
||||
#region Model
|
||||
|
||||
/// <summary>
|
||||
/// The object model used to generate SvgElements descriptors.
|
||||
/// </summary>
|
||||
private const string ModelText = @"// <auto-generated />
|
||||
#nullable disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Svg
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class ElementFactoryAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
internal enum DescriptorType
|
||||
{
|
||||
Property,
|
||||
Event
|
||||
}
|
||||
|
||||
internal interface ISvgPropertyDescriptor
|
||||
{
|
||||
DescriptorType DescriptorType { get; }
|
||||
string AttributeName { get; }
|
||||
string AttributeNamespace { get; }
|
||||
TypeConverter Converter { get; }
|
||||
Type Type { get; }
|
||||
object GetValue(object component);
|
||||
void SetValue(object component, ITypeDescriptorContext context, CultureInfo culture, object value);
|
||||
}
|
||||
|
||||
internal class SvgPropertyDescriptor<T, TU> : ISvgPropertyDescriptor
|
||||
{
|
||||
public DescriptorType DescriptorType { get; }
|
||||
public string AttributeName { get; }
|
||||
public string AttributeNamespace { get; }
|
||||
public TypeConverter Converter { get; }
|
||||
public Type Type { get; } = typeof(TU);
|
||||
private Func<T, TU> Getter { get; }
|
||||
private Action<T, TU> Setter { get; }
|
||||
|
||||
public SvgPropertyDescriptor(DescriptorType descriptorType, string attributeName, string attributeNamespace, TypeConverter converter, Func<T, TU> getter, Action<T, TU> setter)
|
||||
{
|
||||
DescriptorType = descriptorType;
|
||||
AttributeName = attributeName;
|
||||
AttributeNamespace = attributeNamespace;
|
||||
Converter = converter;
|
||||
Getter = getter;
|
||||
Setter = setter;
|
||||
}
|
||||
|
||||
public object GetValue(object component)
|
||||
{
|
||||
return (object)Getter((T)component);
|
||||
}
|
||||
|
||||
public void SetValue(object component, ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (Converter != null)
|
||||
{
|
||||
Setter((T)component, (TU)Converter.ConvertFrom(context, culture, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}";
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Initialize(GeneratorInitializationContext context)
|
||||
{
|
||||
|
@ -109,17 +36,13 @@ namespace Svg
|
|||
/// <inheritdoc/>
|
||||
public void Execute(GeneratorExecutionContext context)
|
||||
{
|
||||
// Add the ElementFactory model source to compilation.
|
||||
context.AddSource("Svg_Model", SourceText.From(ModelText, Encoding.UTF8));
|
||||
|
||||
// Check is we have our SyntaxReceiver object used to filter compiled code.
|
||||
if (!(context.SyntaxReceiver is SyntaxReceiver receiver))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var options = (context.Compilation as CSharpCompilation)?.SyntaxTrees[0].Options as CSharpParseOptions;
|
||||
var compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(ModelText, Encoding.UTF8), options));
|
||||
var compilation = context.Compilation;
|
||||
|
||||
var elementFactoryAttribute = compilation.GetTypeByMetadataName("Svg.ElementFactoryAttribute");
|
||||
if (elementFactoryAttribute is null)
|
||||
|
@ -367,7 +290,7 @@ namespace Svg
|
|||
}}
|
||||
}}
|
||||
");
|
||||
context.AddSource($"Svg_SvgElement_Properties.cs", SourceText.From(source.ToString(), Encoding.UTF8));
|
||||
context.AddSource($"Svg.SvgElement.Properties.g.cs", SourceText.From(source.ToString(), Encoding.UTF8));
|
||||
source.Clear();
|
||||
|
||||
// Generate SvgElement derived classes with descriptor Properties dictionary.
|
||||
|
@ -456,7 +379,7 @@ namespace {namespaceElement}
|
|||
}}
|
||||
}}
|
||||
");
|
||||
context.AddSource($"{namespaceElement.Replace('.', '_')}_{element.Symbol.Name}_Properties.cs", SourceText.From(source.ToString(), Encoding.UTF8));
|
||||
context.AddSource($"{namespaceElement}.{element.Symbol.Name}.Properties.g.cs", SourceText.From(source.ToString(), Encoding.UTF8));
|
||||
source.Clear();
|
||||
}
|
||||
|
||||
|
@ -492,7 +415,7 @@ namespace Svg
|
|||
}
|
||||
}
|
||||
");
|
||||
context.AddSource($"Svg_SvgElements.cs", SourceText.From(source.ToString(), Encoding.UTF8));
|
||||
context.AddSource($"Svg.SvgElements.g.cs", SourceText.From(source.ToString(), Encoding.UTF8));
|
||||
source.Clear();
|
||||
|
||||
// Generate ElementFactory class.
|
||||
|
@ -586,7 +509,7 @@ namespace {namespaceElementFactory}
|
|||
}}
|
||||
}}");
|
||||
|
||||
context.AddSource($"{namespaceElementFactory.Replace('.', '_')}_{elementFactorySymbol.Name}_ElementFactory.cs", SourceText.From(source.ToString(), Encoding.UTF8));
|
||||
context.AddSource($"{namespaceElementFactory}.{elementFactorySymbol.Name}.ElementFactory.g.cs", SourceText.From(source.ToString(), Encoding.UTF8));
|
||||
source.Clear();
|
||||
}
|
||||
|
||||
|
@ -755,6 +678,10 @@ namespace {namespaceElementFactory}
|
|||
{
|
||||
"System.String" => "System.ComponentModel.StringConverter",
|
||||
"System.Single" => "System.ComponentModel.SingleConverter",
|
||||
"System.Int16" => "System.ComponentModel.Int16Converter",
|
||||
"System.Int32" => "System.ComponentModel.Int32Converter",
|
||||
"System.Int64" => "System.ComponentModel.Int64Converter",
|
||||
"System.Boolean" => "System.ComponentModel.BooleanConverter",
|
||||
"System.Uri" => "System.UriTypeConverter",
|
||||
_ => null
|
||||
};
|
||||
|
@ -863,149 +790,5 @@ namespace {namespaceElementFactory}
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Symbol member type.
|
||||
/// </summary>
|
||||
private enum MemberType
|
||||
{
|
||||
/// <summary>
|
||||
/// Property symbol.
|
||||
/// </summary>
|
||||
Property,
|
||||
/// <summary>
|
||||
/// Event symbol.
|
||||
/// </summary>
|
||||
Event
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The SvgElement object property/event.
|
||||
/// </summary>
|
||||
private class Property
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets property/event symbol.
|
||||
/// </summary>
|
||||
public ISymbol Symbol { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets property/event symbol member type.
|
||||
/// </summary>
|
||||
public MemberType MemberType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets property/event attribute name.
|
||||
/// </summary>
|
||||
public string AttributeName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets property/event attribute namespace.
|
||||
/// </summary>
|
||||
public string AttributeNamespace { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets property/event type converter type string.
|
||||
/// </summary>
|
||||
public string? Converter { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Property"/> class.
|
||||
/// </summary>
|
||||
/// <param name="symbol">The property/event symbol.</param>
|
||||
/// <param name="memberType">The property/event symbol member type.</param>
|
||||
/// <param name="attributeName">The property/event attribute name.</param>
|
||||
/// <param name="attributeNamespace">The property/event attribute namespace.</param>
|
||||
/// <param name="converter">The property/event type converter type string.</param>
|
||||
public Property(ISymbol symbol, MemberType memberType, string attributeName, string attributeNamespace, string? converter)
|
||||
{
|
||||
Symbol = symbol;
|
||||
MemberType = memberType;
|
||||
AttributeName = attributeName;
|
||||
AttributeNamespace = attributeNamespace;
|
||||
Converter = converter;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom <see cref="Property"/> equality comparer using <see cref="ISymbol"/> for cmparison.
|
||||
/// </summary>
|
||||
private class PropertyEqualityComparer : IEqualityComparer<Property>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(Property p1, Property p2)
|
||||
{
|
||||
return SymbolEqualityComparer.Default.Equals(p1.Symbol, p2.Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int GetHashCode(Property p)
|
||||
{
|
||||
#pragma warning disable RS1024
|
||||
return p.Symbol.GetHashCode();
|
||||
#pragma warning restore RS1024
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The SvgElement object.
|
||||
/// </summary>
|
||||
private class Element
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets element type symbol.
|
||||
/// </summary>
|
||||
public INamedTypeSymbol Symbol { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets element name.
|
||||
/// </summary>
|
||||
public string? ElementName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets classes that use element name.
|
||||
/// </summary>
|
||||
public List<string> ClassNames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets element properties list.
|
||||
/// </summary>
|
||||
public List<Property> Properties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Element"/> class.
|
||||
/// </summary>
|
||||
/// <param name="symbol">The element type symbol.</param>
|
||||
/// <param name="elementName">The element name.</param>
|
||||
/// <param name="classNames">The classes that use element name.</param>
|
||||
/// <param name="properties">The element properties list.</param>
|
||||
public Element(INamedTypeSymbol symbol, string? elementName, List<string> classNames, List<Property> properties)
|
||||
{
|
||||
Symbol = symbol;
|
||||
ElementName = elementName;
|
||||
ClassNames = classNames;
|
||||
Properties = properties;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The SyntaxReceiver is used to filter compiled code. This enable quick and easy way to filter compiled code.
|
||||
/// </summary>
|
||||
private class SyntaxReceiver : ISyntaxReceiver
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the list of all candidate class.
|
||||
/// </summary>
|
||||
public List<ClassDeclarationSyntax> CandidateClasses { get; } = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
||||
{
|
||||
if (syntaxNode is ClassDeclarationSyntax classDeclarationSyntax)
|
||||
{
|
||||
CandidateClasses.Add(classDeclarationSyntax);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Svg.Generators
|
||||
{
|
||||
/// <summary>
|
||||
/// The SvgElement object.
|
||||
/// </summary>
|
||||
class Element
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets element type symbol.
|
||||
/// </summary>
|
||||
public INamedTypeSymbol Symbol { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets element name.
|
||||
/// </summary>
|
||||
public string? ElementName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets classes that use element name.
|
||||
/// </summary>
|
||||
public List<string> ClassNames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets element properties list.
|
||||
/// </summary>
|
||||
public List<Property> Properties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Element"/> class.
|
||||
/// </summary>
|
||||
/// <param name="symbol">The element type symbol.</param>
|
||||
/// <param name="elementName">The element name.</param>
|
||||
/// <param name="classNames">The classes that use element name.</param>
|
||||
/// <param name="properties">The element properties list.</param>
|
||||
public Element(INamedTypeSymbol symbol, string? elementName, List<string> classNames, List<Property> properties)
|
||||
{
|
||||
Symbol = symbol;
|
||||
ElementName = elementName;
|
||||
ClassNames = classNames;
|
||||
Properties = properties;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
namespace Svg.Generators
|
||||
{
|
||||
/// <summary>
|
||||
/// Symbol member type.
|
||||
/// </summary>
|
||||
enum MemberType
|
||||
{
|
||||
/// <summary>
|
||||
/// Property symbol.
|
||||
/// </summary>
|
||||
Property,
|
||||
/// <summary>
|
||||
/// Event symbol.
|
||||
/// </summary>
|
||||
Event
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Svg.Generators
|
||||
{
|
||||
/// <summary>
|
||||
/// The SvgElement object property/event.
|
||||
/// </summary>
|
||||
class Property
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets property/event symbol.
|
||||
/// </summary>
|
||||
public ISymbol Symbol { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets property/event symbol member type.
|
||||
/// </summary>
|
||||
public MemberType MemberType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets property/event attribute name.
|
||||
/// </summary>
|
||||
public string AttributeName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets property/event attribute namespace.
|
||||
/// </summary>
|
||||
public string AttributeNamespace { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets property/event type converter type string.
|
||||
/// </summary>
|
||||
public string? Converter { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Property"/> class.
|
||||
/// </summary>
|
||||
/// <param name="symbol">The property/event symbol.</param>
|
||||
/// <param name="memberType">The property/event symbol member type.</param>
|
||||
/// <param name="attributeName">The property/event attribute name.</param>
|
||||
/// <param name="attributeNamespace">The property/event attribute namespace.</param>
|
||||
/// <param name="converter">The property/event type converter type string.</param>
|
||||
public Property(ISymbol symbol, MemberType memberType, string attributeName, string attributeNamespace, string? converter)
|
||||
{
|
||||
Symbol = symbol;
|
||||
MemberType = memberType;
|
||||
AttributeName = attributeName;
|
||||
AttributeNamespace = attributeNamespace;
|
||||
Converter = converter;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Svg.Generators
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom <see cref="Property"/> equality comparer using <see cref="ISymbol"/> for cmparison.
|
||||
/// </summary>
|
||||
class PropertyEqualityComparer : IEqualityComparer<Property>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(Property p1, Property p2)
|
||||
{
|
||||
return SymbolEqualityComparer.Default.Equals(p1.Symbol, p2.Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int GetHashCode(Property p)
|
||||
{
|
||||
#pragma warning disable RS1024
|
||||
return p.Symbol.GetHashCode();
|
||||
#pragma warning restore RS1024
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
|
||||
namespace Svg.Generators
|
||||
{
|
||||
/// <summary>
|
||||
/// The SyntaxReceiver is used to filter compiled code. This enable quick and easy way to filter compiled code.
|
||||
/// </summary>
|
||||
class SyntaxReceiver : ISyntaxReceiver
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the list of all candidate class.
|
||||
/// </summary>
|
||||
public List<ClassDeclarationSyntax> CandidateClasses { get; } = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
||||
{
|
||||
if (syntaxNode is ClassDeclarationSyntax classDeclarationSyntax)
|
||||
{
|
||||
CandidateClasses.Add(classDeclarationSyntax);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
### Geneated
|
||||
A directory of the generated source codes.
|
||||
- The generated files are excluded from the repository.
|
||||
- These files will not be directly included in the project.
|
||||
- To view the generated files, turn "Show All Files" on in the VS.
|
|
@ -37,7 +37,7 @@
|
|||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\$(Configuration)\$(TargetFramework)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
|
||||
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
|
|
|
@ -35,10 +35,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Svg.Benchmark", "..\Tests\S
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Generators", "Generators", "{FAFD6DC7-5203-4CED-A151-66379DD43695}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Svg.Custom", "..\Svg.Custom\Svg.Custom.csproj", "{6FAA2B79-FE5C-456B-A743-E9290665B223}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Svg.Tests.Common", "..\Tests\Svg.Tests.Common\Svg.Tests.Common.csproj", "{D7C625E8-79EA-4859-A457-2C4A90786790}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Svg.Custom", "..\Tests\Svg.Custom\Svg.Custom.csproj", "{AD112647-446B-4DAC-8D90-17B0F5FA7188}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -85,14 +85,14 @@ Global
|
|||
{8DEB3EA7-5915-4EB9-8052-85A7AC4379EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8DEB3EA7-5915-4EB9-8052-85A7AC4379EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8DEB3EA7-5915-4EB9-8052-85A7AC4379EC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6FAA2B79-FE5C-456B-A743-E9290665B223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6FAA2B79-FE5C-456B-A743-E9290665B223}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6FAA2B79-FE5C-456B-A743-E9290665B223}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6FAA2B79-FE5C-456B-A743-E9290665B223}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D7C625E8-79EA-4859-A457-2C4A90786790}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D7C625E8-79EA-4859-A457-2C4A90786790}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D7C625E8-79EA-4859-A457-2C4A90786790}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D7C625E8-79EA-4859-A457-2C4A90786790}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AD112647-446B-4DAC-8D90-17B0F5FA7188}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AD112647-446B-4DAC-8D90-17B0F5FA7188}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AD112647-446B-4DAC-8D90-17B0F5FA7188}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AD112647-446B-4DAC-8D90-17B0F5FA7188}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -108,6 +108,7 @@ Global
|
|||
{BACDD1F4-B97D-4E27-BD09-6957633FF484} = {FAFD6DC7-5203-4CED-A151-66379DD43695}
|
||||
{8DEB3EA7-5915-4EB9-8052-85A7AC4379EC} = {2EC3F3A0-F097-43EF-A603-9B82E3061469}
|
||||
{D7C625E8-79EA-4859-A457-2C4A90786790} = {2EC3F3A0-F097-43EF-A603-9B82E3061469}
|
||||
{AD112647-446B-4DAC-8D90-17B0F5FA7188} = {2EC3F3A0-F097-43EF-A603-9B82E3061469}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5096EEB3-8F41-44B5-BCF9-58743A59AB21}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Svg
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class ElementFactoryAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
internal enum DescriptorType
|
||||
{
|
||||
Property,
|
||||
Event
|
||||
}
|
||||
|
||||
internal interface ISvgPropertyDescriptor
|
||||
{
|
||||
DescriptorType DescriptorType { get; }
|
||||
string AttributeName { get; }
|
||||
string AttributeNamespace { get; }
|
||||
TypeConverter Converter { get; }
|
||||
Type Type { get; }
|
||||
object GetValue(object component);
|
||||
void SetValue(object component, ITypeDescriptorContext context, CultureInfo culture, object value);
|
||||
}
|
||||
|
||||
internal class SvgPropertyDescriptor<T, TU> : ISvgPropertyDescriptor
|
||||
{
|
||||
public DescriptorType DescriptorType { get; }
|
||||
public string AttributeName { get; }
|
||||
public string AttributeNamespace { get; }
|
||||
public TypeConverter Converter { get; }
|
||||
public Type Type { get; } = typeof(TU);
|
||||
private Func<T, TU> Getter { get; }
|
||||
private Action<T, TU> Setter { get; }
|
||||
|
||||
public SvgPropertyDescriptor(DescriptorType descriptorType, string attributeName,
|
||||
string attributeNamespace, TypeConverter converter, Func<T, TU> getter, Action<T, TU> setter)
|
||||
{
|
||||
DescriptorType = descriptorType;
|
||||
AttributeName = attributeName;
|
||||
AttributeNamespace = attributeNamespace;
|
||||
Converter = converter;
|
||||
Getter = getter;
|
||||
Setter = setter;
|
||||
}
|
||||
|
||||
public object GetValue(object component)
|
||||
{
|
||||
return (object)Getter((T)component);
|
||||
}
|
||||
|
||||
public void SetValue(object component, ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (Converter != null)
|
||||
{
|
||||
Setter((T)component, (TU)Converter.ConvertFrom(context, culture, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
<IsPackable>True</IsPackable>
|
||||
<Nullable>disable</Nullable>
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\$(Configuration)\$(TargetFramework)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
|
||||
<CompilerGeneratedFilesOutputPath>$(SvgSourcesBasePath)\Generated</CompilerGeneratedFilesOutputPath>
|
||||
<DefineConstants>$(DefineConstants);NO_SDC</DefineConstants>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
@ -24,7 +24,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SvgSourcesBasePath>..</SvgSourcesBasePath>
|
||||
<SvgSourcesBasePath>..\..</SvgSourcesBasePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -42,6 +42,11 @@
|
|||
<Compile Remove="$(SvgSourcesBasePath)\Source\Resources\svg11.dtd" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="$(CompilerGeneratedFilesOutputPath)/**/*.cs" />
|
||||
<Compile Remove="$(SvgSourcesBasePath)\Source\Generated\**\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
|
||||
<DefineConstants>$(DefineConstants);NETSTANDARD;NETSTANDARD20</DefineConstants>
|
||||
</PropertyGroup>
|
Загрузка…
Ссылка в новой задаче