Информация об изменениях

Сообщение Re: Introducing C# Source Generators от 01.05.2020 14:05

Изменено 05.05.2020 14:02 Sinclair

Re: Introducing C# Source Generators
Здравствуйте, Serginio1, Вы писали:

S>https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/

S>Как то новость прошла без энтузиазма
Крутая штука. Надо покрутить.
S> Очень интересен пример AutoNotifyGenerator https://github.com/dotnet/roslyn-sdk/blob/master/samples/CSharp/SourceGenerators/SourceGeneratorSamples/AutoNotifyGenerator.cs
Cходу не понял, нафига они инжектят код атрибута. Такие-то штуки можно просто через Dependency принести, обычным атрибутом как у всех.
Или они хотели избежать необходимости давать ссылку на второй пакет?

S> Раньше использовались Fody Refit которые Il код редактировали.

S>Ну и T4, правда бы еще и синтаксис типа разора

У меня пока есть идея улучшить рефлексию. При работе с ExpressionTrees и ILGenerator адский объём кода уходит на все эти typeof(MemoryMarshal).GetRuntimeMethods().Where(x => x.Name.Equals("Cast")).Select(m => new { Method = m, Parameters = m.GetParameters() }).FirstOrDefault(p =>p.Parameters.Length == 1 && p.Parameters[0].ParameterType.IsGenericType && p.Parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(Span<>)).
Не дожидаясь infoof() (ах, где же ты теперь, блог Липперта...), люди воротят полурешения.
Половинные они потому, что внезапно есть целая куча ограничений — например, метод, возвращающий банальный Span<int>, таким образом не получишь (CS8640). А ещё есть CS8153 и много его друзей.
А так мы можем для интересного нам кода генерировать type class, который для каждого мембера будет иметь одноимённую проперть или метод — типа
public class MemoryMarshalType
{ 
   public static MethodInfo Cast_SpanT<T, R>() 
   public static MethodInfo Cast_ReadonlySpanT<T,R>()
}

public class Span Type<T>
{
   public static PropertyInfo Item{get;}
   public static PropertyInfo Empty { get;} 
   public static PropertyInfo Length { get;}
}

В итоге, вместо
il1.Emit(OpCodes.Call, typeof(Console).GetMethod("Write", new Type[] { typeof(string) }));

пишем
il1.Emit(OpCodes.Call, ConsoleType.Write_String);

(Пока ещё не уверен, что это лучший способ).
Re: Introducing C# Source Generators
Здравствуйте, Serginio1, Вы писали:

S>https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/

S>Как то новость прошла без энтузиазма
Крутая штука. Надо покрутить.
S> Очень интересен пример AutoNotifyGenerator https://github.com/dotnet/roslyn-sdk/blob/master/samples/CSharp/SourceGenerators/SourceGeneratorSamples/AutoNotifyGenerator.cs
Cходу не понял, нафига они инжектят код атрибута. Такие-то штуки можно просто через Dependency принести, обычным атрибутом как у всех.
Или они хотели избежать необходимости давать ссылку на второй пакет?

S> Раньше использовались Fody Refit которые Il код редактировали.

S>Ну и T4, правда бы еще и синтаксис типа разора

У меня пока есть идея улучшить рефлексию. При работе с ExpressionTrees и ILGenerator адский объём кода уходит на все эти typeof(MemoryMarshal).GetRuntimeMethods().Where(x => x.Name.Equals("Cast")).Select(m => new { Method = m, Parameters = m.GetParameters() }).FirstOrDefault(p =>p.Parameters.Length == 1 && p.Parameters[0].ParameterType.IsGenericType && p.Parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(Span<>)).
Не дожидаясь infoof() (ах, где же ты теперь, блог Липперта...), люди воротят полурешения.
Половинные они потому, что внезапно есть целая куча ограничений — например, метод, возвращающий банальный Span<int>, таким образом не получишь (CS8640). А ещё есть CS8153 и много его друзей.
А так мы можем для интересного нам кода генерировать type class, который для каждого мембера будет иметь одноимённую проперть или метод — типа
public class MemoryMarshalType
{ 
   public static MethodInfo Cast_SpanT<T, R>() 
   public static MethodInfo Cast_ReadonlySpanT<T,R>()
}

public class SpanType<T>
{
   public static PropertyInfo Item{get;}
   public static PropertyInfo Empty { get;} 
   public static PropertyInfo Length { get;}
}

В итоге, вместо
il1.Emit(OpCodes.Call, typeof(Console).GetMethod("Write", new Type[] { typeof(string) }));

пишем
il1.Emit(OpCodes.Call, ConsoleType.Write_String);

(Пока ещё не уверен, что это лучший способ).