Как успешно скомпилировать помеченный / помеченный класс с Roslyn - PullRequest
1 голос
/ 28 марта 2019

Я работаю над заказчиком, который хочет сериализовать / десериализовать данный объект в XML и наоборот.Он не будет отмечать все свои классы атрибутами ([XmlElement], [XmlArray] и т. Д.), Которые, по моему мнению, будут лучшим решением, поэтому он хочет сгенерировать динамический класс с заданным объектом, то есть записатьновый класс с теми же объявленными свойствами и добавьте атрибуты для сериализации.Новый класс записывается с помощью StringBuilder, а затем его необходимо скомпилировать и получить новый экземпляр.Проблема заключается в том, что если я пишу атрибуты для сериализации, этот новый класс не компилируется, но если я удаляю атрибуты, класс успешно компилируется, и я могу получить экземпляр.

Здесь код

dynamicClassCode = @"
using System.Xml.Serialization;

namespace Pat.Infrastructure.Communication.Model
{
   public class RequestMessage_Serializable
   {
      [XmlElement]
      public System.DateTime RequestDateTime { get; set; }

      [XmlElement]  
      public System.String RequestUniqueMessageId { get; set; }

      [XmlElement]  
      public System.Version Version { get; set; }

      [XmlElement]  
      public System.String User { get; set; }

      [XmlElement]  
      public System.String Password { get; set; }

      [XmlElement]
      public System.String Terminal { get; set; }

      [XmlElement]
      public System.String Method { get; set; }

      [XmlElement]
      public System.Object Request { get; set; }

      [XmlElement]
      public System.String RequestType { get; set; }

      [XmlElement]
      public System.String EndPointSource { get; set; }

      [XmlElement]
      public System.String ResponseFormatExpected { get; set; }

      [XmlElement]
      public System.Object Configuration { get; set; }

      [XmlElement]
      public System.Boolean OneWay { get; set; }
   }
}"

и

string runtimePath = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\{0}.dll";
var syntaxTree = CSharpSyntaxTree.ParseText(dynamicClassCode);

IEnumerable<MetadataReference> DefaultReferences = new[] {MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Xml")),
                        MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Xml.Serialization")),
                        MetadataReference.CreateFromFile(typeof(object).Assembly.Location)
                        };

CSharpCompilation compilation = CSharpCompilation.Create("DynamicCodeManager",
                new[] { syntaxTree },
                DefaultReferences,
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

using (var dllStream = new MemoryStream())
using (var pdbStream = new MemoryStream())
{
  var emitResult = compilation.Emit(dllStream, pdbStream);
  if (!emitResult.Success)
  {
    var diag = emitResult.Diagnostics;
  }
  else
  {
    dllStream.Seek(0, SeekOrigin.Begin);
    Assembly assembly = Assembly.Load(dllStream.ToArray());
   List<System.Reflection.TypeInfo> typesDeclared = new List<System.Reflection.TypeInfo>(assembly.DefinedTypes);
                    Type type = assembly.GetType(typesDeclared[0].ToString());
                    dynamicObj = Activator.CreateInstance(type);
  }
}

Сообщение, которое я получаю, является следующим: [0] (7,8): ошибка CS0246: сообщение об ошибке XmlElementAttributeAttribute 'no seencontró (указывает, что используется как ссылка?) Microsoft.CodeAnalysis.Diagnostic {Microsoft.CodeAnalysis.CSharp.CSDiagnostic}

Есть идеи?Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 28 марта 2019

Что касается исходной проблемы:

Прежде всего, вам не нужны атрибуты для сериализации классов в XML.Сериализатор по умолчанию автоматически сериализует все открытые свойства и поля.Атрибуты необходимо использовать для управления сериализацией, только если вы хотите отклониться от поведения по умолчанию.

Но также вам не нужно создавать динамические типы во время выполнения для управления сериализацией XML.Вы можете использовать класс XmlAttributeOverrides для имитации определенного типа, имеющего атрибуты управления сериализацией xml, как описано в документации:

Класс XmlAttributeOverrides

0 голосов
/ 28 марта 2019

Что касается этого конкретного вопроса:

Вам необходимо убедиться, что все необходимые ссылки включены и все ссылки происходят из одной среды выполнения (каталога).

Это работает для меня:

IEnumerable<MetadataReference> DefaultReferences = new[] {
            MetadataReference.CreateFromFile(string.Format(runtimePath, "mscorlib")),
            MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Runtime")),
            MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Xml")),
            MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Xml.Serialization")),
            MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Xml.XmlSerializer"))
            };

Обратите внимание, что следующий код, который вы использовали, скорее всего загрузит сборку mscorlib из какого-то другого каталога, кроме 'runtimePath', и тем самым загрузит несовместимую сборку.

MetadataReference.CreateFromFile(typeof(object).Assembly.Location)
...