Roslyn allows you to convert a C # project into an open XML 1C: Enterprise configuration format. With the support of Visual Studio, the C # project is automatically provided with Intellisense, interactive syntax and type checking, refactoring, advanced project search, and XmlDoc support. The custom layout of project documents on disk and a more expressive and economical format makes the C # project at Visual Studio the best choice in versioning systems.
It is clear that from the pure theory to the realization of all the features of 1C is very far. The example given in the article has the following limitations. The example supports several types of objects and several common properties. Attributes of objects can be of the same type, although 1C allows a composite type. Code translation in 1C code is not supported. Implemented English-language names.
')
XML upload configuration 1C
Starting from version 8.3, 1C learned how to upload / download configuration to / from the open XML format. She does it in her original manner. Unloading, for example, UT 11.0.7 takes about 6 minutes. In this case, all configuration files will be dumped into a single directory. Files will be about 10K (ten thousand), approximately 430 MB in size. Such unloading is considered a great achievement in the field of openness, because previously the configuration was packed in a closed cf-format, which could only be recognized by specialized means: through a .Net-compatible cfProject or v8unpack.
This is how one of the XML files Language.Russian.xml looks
<?xml version="1.0" encoding="UTF-8"?> <MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Language uuid="7a630662-cf14-44d7-a01c-08006bb5bffa"> <Properties> <Name></Name> <Synonym/> <Comment/> <LanguageCode>ru</LanguageCode> </Properties> </Language> </MetaDataObject>
Replacing XML constructs with C # definitions
In the C # project, a class is responsible for each 1C object. If this is a directory, then the class is inherited from the Catalog class, the enumeration is inherited from the Enum class. Properties of objects and attributes are denoted by C # attributes.
As a result, the XML-definition of the Russian language will take the form Russian.cs
using System; using Elisy.Configuration.DataAnnotations; using Elisy.Configuration; namespace Test.Languages { [Uuid("7a630662-cf14-44d7-a01c-08006bb5bffa")] [LanguageCode("ru")] public class : Language { } }
References to objects are defined through the types of the CatalogRef <> type. For example, so
[Uuid("e140b824-c8f9-4155-87e6-d408e73ccc69")] [Synonym("ru", "")] public CatalogRef<> ;
Tabular part is defined as TabularSection <line of tabular part>
[Uuid("bb2c088e-8fb3-4469-abd7-ba6b4104ae88")] [GeneratedTypeAttribute(GeneratedTypeCategory.TabularSection, "8ef1c35e-8b55-488f-8e24-61f73d287458", "b300dc36-fe12-41d5-a462-792716a1e508")] [GeneratedTypeAttribute(GeneratedTypeCategory.TabularSectionRow, "92e3cead-a61b-474c-8515-56e4911339c7", "dfa007ab-4185-443f-8d11-f7468a7c195e")] [Synonym("ru", "")] public TabularSection<> ;
The events of the object module and the manager module are implemented as override methods. May look like this:
public override void BeforeWrite(ref bool cancel) { var = Catalog.FindByDescription<>(Description, true); if (!IsFolder && IsNew() && G.ValueIsFilled()) { G.Message(" : " + Description + ". "); cancel = true; return; } if (!IsFolder) .GroupBy("");
It should be noted that the methods are now not translated into 1C code. It remains unclear what to do with the 1C preprocessor directives and whether multiple inheritance of the main 1C objects is necessary. G-stands for global context, since calling functions in C # can only be done in conjunction with a class.
Compiling the CSPROJ project
In the last article
habrahabr.ru/post/245453 the possibility of compiling a single CS file was described. Often you need to compile the whole project - several files.
Roslyn has built-in classes responsible for handling sln-solutions and csproj-projects from Visual Studio. The problem is that they refer to the individual assemblies that come with MSBuild Tools. The latest version of Roslyn refers to the MSBuild Tools 2014 builds, which can not be downloaded separately. The installation is now part of the Visual Studio 14 CTP distribution.
It turned out that the Microsoft. Build.dll v.4 is part of the .Net framework. It has an implementation of reading a C # project file. You can independently implement the joining of this assembly with Roslyn logic and get isolation from MSBuild Tools. The implementation will be something like this:
var project = new Project(projectFilePath); List<string> references = new List<string>(); List<SyntaxTree> trees = new List<SyntaxTree>(); foreach(var item in project.Items) { if (item.ItemType == "Reference") { references.Add(item.EvaluatedInclude); } else if (item.ItemType == "Compile") { string filePathToCompile = System.IO.Path.Combine(project.DirectoryPath, item.EvaluatedInclude); var text = System.IO.File.ReadAllText(filePathToCompile); trees.Add(CSharpSyntaxTree.ParseText(text)); } } var assemblyName = project.GetProperty("AssemblyName").EvaluatedValue; var compilation = CSharpCompilation.Create(assemblyName) .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)) .AddReferences(new MetadataFileReference(typeof(Elisy.Configuration.Configuration).Assembly.Location)) .AddReferences(new MetadataFileReference(typeof(object).Assembly.Location)) .AddSyntaxTrees(trees.ToArray());
If you need to implement more project properties, they can be spied on
in the Roslyn project.Getting XML files compatible with 1C: Enterprise
When generating XML files, the work is mostly done with types, their members and attributes. It turned out that Roslyn CSharpCompilation objects are very limited in funds. Through them, you cannot reach the System.Type types, you cannot get a list of attributes with regard to inheritance. Therefore, for a full analysis, it is better to create an assembly using Roslyn and load it for Reflection analysis:
MemoryStream ms = new MemoryStream(); compilation.Emit(ms); var assembly = Assembly.Load(ms.ToArray());
It is strange that it was not possible to load the assembly as ReflectionOnlyLoad due to the error "missing api-ms-win-core-l1-2-0.dll". The error occurred when trying to read the types included in the assembly. However, the build normally loads and runs through the normal Load call.
Generation of XML files is reduced to enumeration of all types inherited from Configuration and basic objects, to enumeration of properties of objects and attributes.
XML is built using LINQ XML tools, for example, like this:
XElement configurationElement = new XElement(Compiler.MdClasses + "Language", language.GetUuidXml(), new XElement(Compiler.MdClasses + "Properties", new XElement(Compiler.MdClasses + "Name", language.Name), language.GetSynonimXml(), language.GetCommentXml(), new XElement(Compiler.MdClasses + "LanguageCode", language.GetAttribute().Value) ) ); var document = CreateMetadataObjectDocument(configurationElement); document.Save(Path.Combine(outFolder, String.Format("Language.{0}.xml", language.Name)));
It was possible to find out that 1C is loyal to the absence of many tags, replacing them with default values. Therefore, empty values in the XML files can be skipped, thereby reducing the size of the disk. Savings can be quite significant - up to 40 percent. Using cs-files instead of XML gives even greater space savings - up to 60%.
findings
Using Visual Studio, it is theoretically possible to create an alternative 1C configurator. For further advancement of the idea, it is necessary to accept agreements regarding all basic objects, storage of forms, translation of the C # language into 1C, 1C preprocessor directives, conventional layouts and SKD layouts;
The current XML upload from 1C is inconvenient for analysis, because all the files are collected in a single directory;
The current XML unloading of 1C is redundant, and its size can be reduced without losing data up to 40%, and storing source codes in the form of C # will save up to 60 percent of disk space;
Reading csproj projects and Visual Studio sln solutions with Roslyn embedded tools is not easy to implement due to the complex availability of MSBuild Tools 2014. Now you can compensate with the .Net Framework 4 classes and with your own Roslyn initialization.
Elisy.Configuration.zip (2.19 mb)