Существует ли способ создать новый тип во время Времени выполнения?

Как ни странно, Android не предоставляет приличного списка цветов. И я говорю странно, потому что за свою 30-летнюю карьеру это первый язык, который я встретил, который не делает этого. И это несмотря на то, что оно построено на Java, которая определяет цвета во всех основных библиотеках.

Те, которые определены, имеют префикс, так что вы не найдете их :) Чтобы найти их (при использовании eclipse), перейдите в документ XML, где вам нужен цветовой тип android: background = "@ android: color / и выполните Ctrl Пробел. В моей версии (текущей, как мы говорим) я получаю более десятка, например: holo_orange_dark

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

20
задан Michiel de Mare 16 June 2009 в 23:30
поделиться

4 ответа

Добавление свойства к существующему типу невозможно, но вы можете создать новый тип во время выполнения с помощью Reflection.Emit. Это довольно сложный материал, и выглядит он примерно так:

AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(
      assemblyName , AssemblyBuilderAccess.Run, assemblyAttributes);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName");
TypeBuilder typeBuilder = moduleBuilder.DefineType(
      "MyNamespace.TypeName" , TypeAttributes.Public);

typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);

// Add a method
newMethod = typeBuilder.DefineMethod("MethodName" , MethodAttributes.Public);

ILGenerator ilGen = newMethod.GetILGenerator();

// Create IL code for the method
ilGen.Emit(...);

// ...

// Create the type itself
Type newType = typeBuilder.CreateType();

Этот код - всего лишь образец. Он мог содержать ошибки.

Вы также можете генерировать классы, компилируя исходный код C # во время выполнения с помощью System.CodeDom, но я не очень много об этом знаю.

24
ответ дан 30 November 2019 в 00:05
поделиться

Взгляните на пространство имен System.Reflection.Emit . Я никогда не использовал его сам, но классы в этом пространстве имен можно использовать для генерации IL (промежуточного языка).

5
ответ дан 30 November 2019 в 00:05
поделиться

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

public static Type[] DynamicTypes;

public void CreateObjects()
{
  var codeNamespace = new CodeNamespace( "DynamicClasses" );
  codeNamespace.Imports.Add( new CodeNamespaceImport( "System" ) );
  codeNamespace.Imports.Add( new CodeNamespaceImport( "System.ComponentModel" ) );

  for( var i = 0; i < 2000; i++ )
  {
    var classToCreate = new CodeTypeDeclaration( "DynamicClass_" + i )
    {
      TypeAttributes = TypeAttributes.Public
    };
    var codeConstructor1 = new CodeConstructor
    {
      Attributes = MemberAttributes.Public
    };
    classToCreate.Members.Add( codeConstructor1 );

    codeNamespace.Types.Add( classToCreate );
  }

  var codeCompileUnit = new CodeCompileUnit();
  codeCompileUnit.Namespaces.Add( codeNamespace );

  var compilerParameters = new CompilerParameters
  {
    GenerateInMemory = true,
    IncludeDebugInformation = true,
    TreatWarningsAsErrors = true,
    WarningLevel = 4
  };
  compilerParameters.ReferencedAssemblies.Add( "System.dll" );

  var compilerResults = new CSharpCodeProvider().CompileAssemblyFromDom( compilerParameters, codeCompileUnit );

  if( compilerResults == null )
  {
    throw new InvalidOperationException( "ClassCompiler did not return results." );
  }
  if( compilerResults.Errors.HasErrors )
  {
    var errors = string.Empty;
    foreach( CompilerError compilerError in compilerResults.Errors )
    {
      errors += compilerError.ErrorText + "\n";
    }
    Debug.Fail( errors );
    throw new InvalidOperationException( "Errors while compiling the dynamic classes:\n" + errors );
  }

  var dynamicAssembly = compilerResults.CompiledAssembly;
  DynamicTypes = dynamicAssembly.GetExportedTypes();
}
5
ответ дан 30 November 2019 в 00:05
поделиться

Вы можете взглянуть на пространство имен System.CodeDom . Согласно одной из страниц, на которые есть ссылки оттуда:

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

Я совсем не эксперт в этом, я просто вспомнил, что видел это на моем плакате .NET Framework на стене. :)

Изменить: С момента написания этого ответа я немного поигрался с System.CodeDom. Я написал сообщение в блоге , в котором используется базовый код CodeDom, который может помочь тем, кто хочет начать с ним.

3
ответ дан 30 November 2019 в 00:05
поделиться