Программно генерировать сборки из OWL файлов с помощью ROWLEX

Я использовал библиотеку ROWLEX для обработки RDF-s. Он поставляется с графическим инструментом designtime под названием OwlGrinder.exe, который может генерировать классы-помощники С# (сборки .NET, если быть точным) из моих онтологий OWL. Интересно, знает ли кто-нибудь, могу ли я сделать то же самое программно во время выполнения.

Ответ 1

ROWLEX просто стал открытым исходным кодом, так что теперь у вас есть шанс заглянуть внутрь кода OwlGrinder.exe и скопировать код оттуда. Однако, вот краткий пример:

    private NC3A.SI.Rowlex.AssemblyGenerator generator;

    private void RunAssemblyGeneration(XmlDocument ontologyFileInRdfXml)
    {
        this.generator = new NC3A.SI.Rowlex.AssemblyGenerator();
        this.generator.GenerateAsync(ontologyFileInRdfXml, "myAssemblyName", 
                                        null, this.OnGenerationFinished);
    }

    private void OnGenerationFinished(string errorMessage)
    {
        if (errorMessage == null)
        {
            // Success
            // Displaying warnings and saving result
            string[] warnings = this.generator.Warnings;
            this.generator.SaveResult(@"C:\myAssemblyName.dll");
                // Important! One generator instance can be executed only once. 
                this.generator = null; 
                this.RejoiceOverSuccess();
            }
        else
        {
                // Failure
                this.MournOverFailure();
            }

    }

Если вы хотите генерировать сборки во время выполнения, я предполагаю, что вы можете повторять это снова и снова, как этого требует ваш пользователь. Вы должны следить здесь, потому что .NET не позволяет вам выгружать сборку. Поэтому вы не можете избавиться от сборок от ваших предыдущих запусков. Решение состоит в том, что вы каждый раз выполняете код генерации в новом AppDomain, который может быть выгружен. OwlGrinder.exe делает именно это, вы можете захотеть пик внутри MainForm.cs

Ответ 2

Да, мистер Ламе, вы можете программно генерировать код .NET.

Есть несколько вариантов.

  • Создайте код как текст.
    Вы можете скомпилировать любой .cs или .vb исходный файл из приложения. См. Справку для класса Microsoft.CSharp.CSharpCodeProvider для стартера. Вы программно вызываете компилятор, указывая ресурсы для встраивания, куда помещать сгенерированную сборку, зависимости и т.д. Один сценарий здесь использует файл template.cs, встраивает в него немного больше кода и затем компилирует его. Результатом является сборка (.dll или .exe или .netmodule, если хотите) в результате этого кода. Затем вы можете загрузить эту сборку и вызвать ее, используя отражение.

  • Создайте код с помощью объектной модели документа.
    Соответствующая область функций здесь называется "CodeDom", и она работает как HTML DOM для веб-страниц, за исключением того, что объектная модель документа используется для создания .NET-кода. Программно вы создаете код, используя элементы DOM.

пример объекта CodeDom:

var class1 = new System.CodeDom.CodeTypeDeclaration(className);
class1.IsClass=true;
class1.TypeAttributes = System.Reflection.TypeAttributes.Public;
class1.Comments.Add(new System.CodeDom.CodeCommentStatement("This class has been programmatically generated"));
// add a constructor to the class
var ctor= new System.CodeDom.CodeConstructor();
ctor.Attributes = System.CodeDom.MemberAttributes.Public;
ctor.Comments.Add(new System.CodeDom.CodeCommentStatement("the null constructor"));
class1.Members.Add(ctor);

// add one statement to the ctor:  an assignment
// in code it will look like;  _privateField = new Foo(); 
ctor.Statements.Add(new System.CodeDom.CodeAssignStatement(new System.CodeDom.CodeVariableReferenceExpression("_privateField"), new System.CodeDom.CodeObjectCreateExpression(fooType)));


// include a private field into the class
System.CodeDom.CodeMemberField field1;
field1= new System.CodeDom.CodeMemberField();
field1.Attributes = System.CodeDom.MemberAttributes.Private;
field1.Name= "_privateField";
field1.Type=new System.CodeDom.CodeTypeReference(fooType);
class1.Members.Add(field1);

и т.д. Вы можете добавлять регулярные методы, всевозможные операторы в коде и т.д. AFAIK. Свойство CodeDom поддерживает все, что поддерживает язык. Вы можете делать выражения lambdas и linq, условные выражения и поток управления, что угодно.

Затем вы можете скомпилировать этот класс и снова создать сборку, которую вы можете сохранить на диск или сохранить в памяти и загрузить динамически.