mercredi 13 décembre 2023

How to match typeof(

I'm using reflection to determine how to format properties on an object.

Here's a dictionary of formatters:

var formatters = new Dictionary<Type, Func<object, object>>()
{
    { typeof(Enum), x => ((Enum)x)?.FormatEnum() },
    { typeof(DateTime?), x => ((DateTime?)x)?.ToShortDateString() },
    { typeof(string), x => x.ToString().ToLower() }
};

Most types will work fine, however when I get the type of my nullable enum TaskStatus, the type is not "Enum", it's the name of the type.

I noticed the base type is "Enum", however I don't want to have to check the base type since most other types will work just fine with the type.

For example, checking the type of string works fine:

typeof(string).FullName = "System.String"

But for the TaskStatus enum:

typeof(Enums.TaskStatus).FullName = "Enums.TaskStatus"

So typeof(Enum) != typeof(Enums.TaskStatus) which is what is preventing the dictionary from finding a match.

Is there any way to find a match in the formatters dictionary without having to put in all the different nullable enum type names I am using?

Edit:

Here's my entire code:

public class NoteHistory
{
    [JsonProperty("Status")]
    public TaskStatus? TaskStatus { get; set; }
    [JsonProperty("CreatedDate")]
    public DateTime? CreatedDate { get; set; }
    [JsonProperty("Description")]
    public string Description { get; set; }
    public bool IsDeleted { get; set; } // not interested in comparing this
}

public enum TaskStatus
{
    ToDo,
    Done
}

public static void DisplayValues()
{
    var noteHistory1 = new NoteHistory
    {
        TaskStatus = TaskStatus.ToDo
    };

    var noteHistory2 = new NoteHistory
    {
        TaskStatus = TaskStatus.Done
    };

    // Get all properties with JsonProperty attr.
    var propertiesToCompare = typeof(NoteHistory)
        .GetProperties()
        .Where(x => x.CustomAttributes
            .Any(y => y.AttributeType.Name == nameof(JsonPropertyAttribute)));

    var comparers = new Dictionary<Type, Func<object, object, bool>>
    {
        { typeof(string), (x, y) => !string.Equals(x?.ToString(), y?.ToString(), StringComparison.InvariantCultureIgnoreCase) }
    };

    var formatters = new Dictionary<Type, Func<object, object>>()
    {
        { typeof(Enum), x => ((Enum)x)?.FormatEnum() }, // doesn't work
        { typeof(DateTime?), x => ((DateTime?)x)?.ToShortDateString() },
        { typeof(string), x => x.ToString().ToLower() },
    };

    foreach (var propertyToCompare in propertiesToCompare)
    {
        var prop1Value = propertyToCompare.GetValue(noteHistory1);
        var prop2Value = propertyToCompare.GetValue(noteHistory2);

        Func<object, object, bool> comparer;
        comparers.TryGetValue(propertyToCompare.PropertyType, out comparer);

        var hasChanged = comparer?.Invoke(prop1Value, prop2Value) ?? prop1Value != prop2Value;

        if (hasChanged)
        {
            Func<object, object> formatter;
            formatters.TryGetValue(propertyToCompare.PropertyType, out formatter);

            var formattedValue = formatter?.Invoke(noteHistory2);
            // TODO: display the value
        }
    }
}




mardi 5 décembre 2023

Cannot always get reflect info for func signature in Go

I have this which returns a string representation of a function signature:

func getFuncSignature(v interface{}) string {

    funcValue := reflect.ValueOf(v)
    funcType := funcValue.Type()
    name := funcType.Name()

    // Function signature
    var params []string
    for i := 0; i < funcType.NumIn(); i++ {
        nm := funcType.In(i).Name()
        if strings.TrimSpace(nm) == "" {
            nm = "<unk>"    // <<<<<<<<<<<<<<<<<<<<< HERE 1
        }
        params = append(params, nm)
    }

    var returns []string
    for i := 0; i < funcType.NumOut(); i++ {
        nm := funcType.Out(i).Name()
        if strings.TrimSpace(nm) == "" {
            nm = "<unk>"  // <<<<<<<<<<<<<<<<<<<<<< HERE 2
        }
        returns = append(returns, nm)
    }

    paramsStr := strings.Join(params, ", ")
    returnsStr := strings.Join(returns, ", ")

    if name != "" {
        return fmt.Sprintf("(func %s(%s) => (%s))", name, paramsStr, returnsStr)
    }

    return fmt.Sprintf("(func(%s) => (%s))", paramsStr, returnsStr)
}

however, some parameter and return types return empty strings, so I put in "" which isn't really ideal. Is there some way to retrieve the names/types of the input and return values?





lundi 4 décembre 2023

C#: how to check if a property type is string? (nullable string) or string [duplicate]

giving this code:

var t = typeof(Sample);
var p1 = t.GetProperty(nameof(Sample.Str1));
var p2 = t.GetProperty(nameof(Sample.Str2));

Console.WriteLine(p1!.PropertyType == p2!.PropertyType);

public class Sample
{
    public string Str1 { get; set; } = default!;
    public string? Str2 { get; set; }
}

in a dotnet project with <Nullable>enable</Nullable> in csproj it prints "True"

but using int instead of string it shows "False".

Is there any way to know if the propertyType is the source code is "string" or "string?" ?





C# Merge Null Or Not Existing Properties and its properties from strongly typed Model after deserialization

The problem is I have a config which I can update using my Model, I deploy new update and user won't get updated configuration file, so it will cause null reference exception, etc. Now I just set default values or use new() to make it at least similar to latest configuration value, but its a hell, I need to always support it, what if I'll or someone else even forget to merge null properties?

I have 3 different config files (YAML, XML, JSON),but with single one model. I want it to merge all null properties, arrays of the arrays, not existing items of the array from default config into existing config, properties of the properties, etc, however I want to save all existing things from the deserialized config.

My Model:

[Serializable]
public class GuardSettings
{
    public GuardSettings()
    {
    }

    public UnturnedGuardOptions UnturnedGuardOptions { get; set; }
    public UnturnedIntegrityVault UnturnedIntegrityVault { get; set; }
    public LocalTimeOptions LocalTimeOptions { get; set; }
    [YamlIgnore, XmlIgnore] public VanillaOptions VanillaOptions { get; set; }
    public LogReport LogReport { get; set; }
    public DiscordWebhookLaunch DiscordWebhookLaunch { get; set; }
    public DiscordWebhookReject DiscordWebhookReject { get; set; }
    public DiscordWebhookAccept DiscordWebhookAccept { get; set; }
    public DiscordWebhookCancel DiscordWebhookCancel { get; set; }
    public DiscordWebhookReport DiscordWebhookReport { get; set; }
    public DiscordWebhookBans DiscordWebhookBans { get; set; }
    public DiscordWebhookUnbans DiscordWebhookUnbans { get; set; }
    public DatabaseOptions DatabaseOptions { get; set; }
    public UnturnedPanelIntegration UnturnedPanelIntegration { get; set; }
    public BanOptions BanOptions { get; set; }
    public PlayerWhitelist PlayerWhitelist { get; set; }
    public HWIDHistory HWIDHistory { get; set; }
    [YamlMember(Alias = "tpsOptions")] public TPSOptions TPSOptions { get; set; }
    public FeaturesOptions FeaturesOptions { get; set; }
    public Feature[] Features { get; set; }
}

[Serializable]
public class Feature
{
    public Feature()
    {
    }

    public string Name { get; set; } = string.Empty;
    public bool Enabled { get; set; }
    public Argument[] Arguments { get; set; } = Array.Empty<Argument>();
}

[Serializable]
public class Argument
{
    public Argument()
    {
    }

    public string? Name { get; set; }
    public object? Value { get; set; }
}

This is how I see it, I have default settings just using my custom factory that configures default config with all properties (in a proper way), and the existing settings is a deserialized config from file (YAML, XML or JSON).

private static GuardSettings Merge(GuardSettings defaultSettings, GuardSettings existingSettings)

After that I want to serialize the Merged config to let configuration being updated, so user can change newest properties and be up to date with changes in the config!

I tried to use Reflection and AutoMapper, but with no success.





dimanche 3 décembre 2023

Using unity game service cloud save - how to retrieve multiple keys at once and load them to appropriate variables

I am using unity game service cloud save to backup important player data. This works great when I use it to save variable(s). However, I cannot figure out how to load variables without hardcoding each possible combination. I am confident there is something simple I am missing, but I do not know what it is, and the AI suggestions I get are off, likely because I am asking the wrong questions.

Please help?

Working function to load multiple variables to the cloud:

    private async Task<string> CloudSaveMultipleValues(Dictionary<string, object> valuesToSave)
{
    try
    {
        await CloudSaveService.Instance.Data.Player.SaveAsync(valuesToSave);

        Debug.Log($"Successfully saved data to cloud");
    }
    catch (CloudSaveValidationException e)
    {
        Debug.LogError(e);
    }
    catch (CloudSaveRateLimitedException e)
    {
        Debug.LogError(e);
    }
    catch (CloudSaveException e)
    {
        Debug.LogError(e);
    }

    return null;
}

Example of the 'valuesToSave input:

allStats_dict = new Dictionary<string, object>
{
    { nameof(gm.stats_CloudSave.gameVersion), gm.stats_CloudSave.gameVersion },
    { nameof(gm.stats_CloudSave.numsPlaced), gm.stats_CloudSave.numsPlaced },
    { nameof(gm.stats_CloudSave.points), gm.stats_CloudSave.points },
    { nameof(gm.stats_CloudSave.gamesPlayed), gm.stats_CloudSave.gamesPlayed },
    { nameof(gm.stats_CloudSave.dateOfFirstGame), gm.stats_CloudSave.dateOfFirstGame }
};

The loading function I am trying to get to work:

private async Task<string> RetrieveSpecificCloudData(HashSet<string> keys)
    {
        try
        {
            var results = await CloudSaveService.Instance.Data.Player.LoadAsync(keys);

            //this confirms I got all the keys I asked for
            Debug.Log($"{results.Count} elements loaded!");

            //this confirms the values are correct
            Debug.Log($"numsPlaced: {results["numsPlaced"].Value.GetAs<int>()}");
            Debug.Log($"dateOfFirstGame: {results["dateOfFirstGame"].Value.GetAs<DateTime>()}");

            //what I cannot figure out is how to assign the value of each key to the appropriate variable???
            //I can hardcode it like this, which works, but there has to be a better way so I do not have to hardcode so many different scenarios... (one for each combination of keys)
            gm.stats_CloudSave.numsPlaced = results["numsPlaced"].Value.GetAs<int>();

            //I need something here that loops through the input (keys), and assigns the value of each key to the appropriate variable. AI tools suggested using reflection, but I can't get it to work...
        }
        catch (CloudSaveValidationException e)
        {
            Debug.LogError(e);
        }
        catch (CloudSaveRateLimitedException e)
        {
            Debug.LogError(e);
        }
        catch (CloudSaveException e)
        {
            Debug.LogError(e);
        }

        return null;
    }

Example of the 'keys' input Hashset:

HashSet<string> keys = new HashSet<string>
    { nameof(gm.stats_CloudSave.numsPlaced),
      nameof(gm.stats_CloudSave.dateOfFirstGame)
    };




samedi 2 décembre 2023

Typescript satisfies condition with Record and generics does not work

This question is related to my other one How to store "types" and instantiate them dynamically in typescript.

Now I'm trying to add generics and abstract base classes into the mix. VsCode complains about everything. And I've tried to tweak the satisfies condition, but nothing works.

Handlers records

    private handlers = {
    [types.CommandType.Click]: handlers.ClickCommandHandler,
    [types.CommandType.Navigate]: handlers.NavigateCommandHandler,
    [types.CommandType.Type]: handlers.TypeCommandHandler,
    [types.CommandType.NewTab]: handlers.NewTabCommandHandler,
    [types.CommandType.AnalyzePage]: handlers.AnalyzePageCommandHandler,
    [types.CommandType.Connect]: handlers.ConnectCommandHandler,
} satisfies Record<types.CommandType, (new <TCommad extends types.AutomationCommand, TResponse>(pageAwaiter: Awaiter, tabs: Map<number, TabSession>) => CommandHandler<TCommad, TResponse>)>;

Error:

Type of computed property's value is 'typeof ClickCommandHandler', which is not assignable to type 'new <TCommad extends AutomationCommand, TResponse>(pageAwaiter: Awaiter, tabs: Map<number, TabSession>) => CommandHandler<TCommad, TResponse>'.
  Types of construct signatures are incompatible.
    Type 'new (pageAwaiter: Awaiter, tabs: Map<number, TabSession>) => ClickCommandHandler' is not assignable to type 'new <TCommad extends AutomationCommand, TResponse>(pageAwaiter: Awaiter, tabs: Map<number, TabSession>) => CommandHandler<TCommad, TResponse>'.
      Construct signature return types 'ClickCommandHandler' and 'CommandHandler<TCommad, TResponse>' are incompatible.
        The types of 'handle' are incompatible between these types.
          Type '(command: ClickCommand) => Promise<AutomationResponse<boolean>>' is not assignable to type '(command: TCommad) => Promise<AutomationResponse<TResponse>>'.
            Types of parameters 'command' and 'command' are incompatible.
              Type 'TCommad' is not assignable to type 'ClickCommand'.
                Type 'AutomationCommand' is missing the following properties from type 'ClickCommand': tabId, selector

CommandHandler, ClickCommandHandler and TabCommandHandler:

export interface CommandHandler<TCommand extends AutomationCommand, TResponse> {
    handle(command: TCommand): Promise<AutomationResponse<TResponse>>;
}
class ClickCommandHandler extends TabCommandHandler<ClickCommand, boolean>
abstract class TabCommandHandler<TCommand extends TabAutomationCommand, TResponse> implements CommandHandler<TCommand, TResponse>

Here's the smallest reproducible Typescript Playground.

This should be simple, what am I missing?





vendredi 1 décembre 2023

c# Enumerable Reflection GetMethod not found method [duplicate]

I have code for getting method Select for Enumerable.

var selectMethod = typeof(Enumerable).GetMethod("Select", BindingFlags.Public | BindingFlags.Static, [typeof(IEnumerable<>), typeof(Func<,>)]);

I getting null. But when i debbugging in source code was method as candidate with exact types as IEnumerable and Func but they were slightly different like they don't have AssemblyQualifiedName and some other fields, it was RuntimeType or something as i know, and as result type which getting in source code is not assignable from type what in method parameters.

I tried other types, but it alsways null.

typeof(IEnumerable<>)
typeof(IEnumerable)
typeof(Enumerable)

I can get method like that and it working.

var selectMethod = typeof(Enumerable).GetMethods()
            .Where(m => m.Name == nameof(Enumerable.Select))
            .First(m => m.GetParameters().Length == 2)
            .MakeGenericMethod(elementType, elementType);

But i interested why GetMethod not working in that case





jeudi 30 novembre 2023

Kotlin reflection application to parsing, an example

I am experimenting with Kotlin's reflection mechanism. However, things go wrong when I try to apply the function recursively. I have been learning Kotlin for less than a month now and I am completely out of my depth here. Please guide me?

import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty
import kotlin.reflect.full.findAnnotation

annotation class CsByte
annotation class CsStruct

class Struct1 {
    @CsByte
    var x: Int = 0
    @CsStruct
    var inner1: Inner = Inner()
}

class Inner {
    @CsByte
    var y: Int = 0
}

fun <T : Any> parseStructRecursively (type:KClass<T>): T {
    val obj = type.constructors.find { it.parameters.isEmpty() }?.call()!!
    for (field in type.members) {
        if (field.findAnnotation<CsByte>() != null)
            (field as KMutableProperty<*>).setter.call(obj, 9)
        if (field.findAnnotation<CsStruct>() != null)
            (field as KMutableProperty<*>).setter.call(obj, parseStructRecursively(field::class))
            //                                                                     ^^^^^^^^^^^^ wrong?
            // Inner::class works OK,  field::class fails because it does not have argumentless constructor.
    }
    return obj
}

inline fun <reified T : Any> parseReified (): T {
    return parseStructRecursively(T::class)
}

fun main() {
    var s1 = parseReified<Struct1>()
    println(s1.x == 9)
    println(s1.inner1.y == 9)
}




mercredi 29 novembre 2023

Is there a way to check if kotlin class property was defined as nullable at runtime?

I have the following simple class structure:

package qwerty

import kotlin.reflect.full.declaredMemberProperties

class UserSet(
    var user1: User,
    var user2: User? = null,
)

class User(
    var id: Long
)

fun main(args: Array<String>) {
    val type = UserSet::class
    type.declaredMemberProperties // ???
}

In UserSet the first user is non-null, while the second is nullable. There definetly should be a way how to check if a property was defined as nullable at runtime having KClass object, but i don't have an idea how to do it.

I found isMarkedNullable in outType in _descriptor in idea evaluate window during debug, but i can't get access to it from my code.

So the question is how to check if properties of a class defined as nullable in runtime?

enter image description here enter image description here





How to determine if `object?` is nullable? [duplicate]

The following test fails:

#nullable enable
using System;
using FluentAssertions;
using Xunit;

public class TypeExtensionsTests
{
    [Fact]
    public void TestIsNullable()
    {
        object? o = new();
        var type = o.GetType();

        bool isNullable = type.IsNullable();

        isNullable.Should().BeTrue();
    }
}

public static class TypeExtensions
{
    public static bool IsNullable(this Type type)
    {
        return Nullable.GetUnderlyingType(type) != null;
    }
}

How to reliably establish that a Type instance is actually a nullable type?

This question does not answer my question, since the top answer is the implementation of the failing test.





How can I replicate this java code in golang?

A client has decided to convert some code to java in a binary using golang...

having this example in java:

[..]
String aa = java.lang.ProcessBuilder;
String bb = start;
String tsil = "somestuff.exe";

Class kj = Class.forName(aa);
Process w = (Process) kj.getMethod(bb).invoke(kj.getDeclaredConstructors()[0].newInstance(tsil));
InputStream error = w.getErrorStream();
OutputStream ot = w.getOutputStream();
[..]

which basically is:

Process process = new ProcessBuilder("somestuff.exe").start();

how can i do the same thing using the reflection and dynamic method invocation in golang to execute commands/ binaries like this:

cmd := exec.Command("somestuff.exe")
err := cmd.Start()




mardi 28 novembre 2023

Adding my static variable in java annotataed class

How i can to add my static variable to class, like in Log4j2?

For example:

import lombok.extern.log4j.Log4j2;

@Log4j2
public class TestClass {
    public void test() {
        log.info("test");
    }
}

and generated source class looks like:

public class TestClass {
    @Generated
    private static final Logger log = LogManager.getLogger(TestClass.class);
    
    public void test() {
        log.info("test");
    }
}

I created the class that extends javax.annotation.processing.AbstractProcessor and try to modify the original class by adding some static string, but I don't know how to do it right :/

@SupportedAnnotationTypes("TestAnnotation")
@SupportedSourceVersion(SourceVersion.RELEASE_17)
public class TestProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (Element element : roundEnv.getElementsAnnotatedWith(TestAnnotation.class)) {
            if (element.getKind().isClass()) {
                // ???
            }
        }
        return true;
    }
}

I want something like:

@TestAnnotation
public class TestClass {
    public void test() {
        System.out.println(testString); // testString is inserted by TestProcessor 
    }
}




vendredi 24 novembre 2023

How can I add value to a reflected variable?

I want to add value to a value I got through reflection. The += does not work and SetValue does not fit my needs. *

  • Instance.Field does exist but this would not be good for my script(For reasons).

Here is my class:

public class OreMine : MonoBehaviour
{
    [SerializeField] string VariableName;

    void OnCollisionEnter2D(Collision2D col)
    {
        if(col.gameObject.tag == "Player")
        {
            var Value = typeof(Inventory).GetField(VariableName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
            Destroy(gameObject);
        }
    }
}

The problem is that I could not do this:

Value += 1

And this would not suit my needs:

public class OreMine : MonoBehaviour
{
valueField.SetValue(null, SomeInteger);
}

And in Microsoft documentation the AddValue seems like it's only for strings.

https://learn.microsoft.com/en-us/dotnet/api/system.runtime.serialization.serializationinfo.addvalue?view=net-8.0





jeudi 23 novembre 2023

How can I convert a TS Type/Interface into an object with the keys for that type and the primitives it's made of?

Explanation with an example:

I have the following TS interfaces/types:

interface Stock {
    name: string;
    value: number;
}

type Account = {
    username: string;
    portfolio: Stock[];
}

I now want to have some magic function to turn the Account type into an object like this:

{
  username: {
    type: 'string',
  },
  portfolio: {
    type: 'array',
    items: {
      type: 'object',
      properties: {
        name: {
          type: 'string',
        },
        value: {
          type: 'number',
        },
      },
    },
  },
}

This might be asking for too much since 'array' is not a JS primitive, so maybe that should be 'object' instead - but I hope this gets the idea across.

Very important to note where is that I don't nessecarily have an object that conforms to this type in runtime - I only have the interface/type - no objects to actually go through.

I believe this topic is related to reflection, but any ideas on how to achieve something like this would be appreciated.

The idea is to be able to do this in runtime which is where the trouble comes from. I want to generate an AST from the interfaces/types and have it recursively travel all the interfaces/types that are being used by all the libraries.





BehaviourSubject does not update template

I have an Angular 17 online store and I'm having problemas with BehaviourSubject not updating a components template.

Clients choose products and they are stored on a CartProduct class: id, name, num (number of elements of that product). Then everything is managed in a CartService that has a BehaviourSubject to store them:

@Injectable({
  providedIn: "root",
})
export class CartService {
  cartSubject: BehaviorSubject<CartProduct[]> = new BehaviorSubject<CartProduct[]>([]);

  get cart$(): Observable<CartProduct[]> {
    return this.cartSubject.asObservable();
  }
  
  ...
}

It also has an "add" method who receives a CartProduct item. This method checks if the product is already on the cart, if the product is already on the list it just increases the "num" counter and if it is not, it adds it:

add(cartProd: CartProduct) {
  const currentCart: CartProduct[] = this.cartSubject.getValue();
  const ind: number = currentCart.findIndex((x: CartProduct): boolean => x.id === cartProd.id);
  if (ind != -1) {
    currentCart[ind].num += cartProd.num;
  else {
  }
    currentCart.push(cartProd);
  }
  this.cartSubject.next(currentCart);
}

The store is composed of three components (quite a lot more, but it's not the issue :P): HomeComponent, HeaderComponent and OneProductComponent.

The HomeComponent has a header that shows a sidebar with the list of elements in the cart:

import { Component, OnInit } from '@angular/core';
import { CartService } from './cart.service';

@Component({
  selector: 'app-header',
  template: `
    <ul>
      @for (product of cart; track product.id) {
      <li>
        
      </li>
      }
    </ul>
  `,
  styleUrls: ['./header.component.css'],
})
export class HeaderComponent implements OnInit {
  cart: CartProduct[] = [];

  constructor(private cartService: CartService) {}

  ngOnInit() {
    this.cartService.cart$.subscribe(() => {
      this.cart = this.cartService.cart$.value;
    });
  }
}

There is a list of products on the home that are called OneProductComponent, basically a picture, a name and a button to add it to the cart.

import { Component } from '@angular/core';
import { CartService } from './cart.service';

@Component({
  selector: 'app-one-product',
  template: `
    <h2></h2>
    <p> €</p>
    <button (click)="addProduct()">Add product</button>
  `,
  styleUrls: ['./one-product.component.css'],
})
export class OneProductComponent {
  constructor(private cartService: CartService) {}

  addProduct() {
    this.cartService.add({
      id: 1,
      name: 'Product 1',
      price: 10,
      num: 1,
    });
  }
}

The problem is that when I click the button on the component, it doesn't reflect on the header. If I navigate somewhere else the header updates correctly and shows the cart, but the moment I hit the add button it just does nothing.

I have also added this after the "add" call to the service:

console.log(this.cartService.cartSubject.value);

And I see that the product is correctly added to the cart. But nothing happens. I also tried adding an EventEmitter on the cart's add method and subscribing to it on the header:

CartService:

public productAdded$: EventEmitter<void>;

add(product: CartProduct) {
  ...
  this.cartSubject.next(currentCart);
  this.productAdded$.emit();
}

HeaderComponent:

constructor(cartService: CartService) {
  this.cartService.productAdded$.subscribe((): void => { console.log('product added'); });
}

And also nothing happens. It looks like it subscribes correctly on load and the cart is shown, but when I do any change the template doesn't update.

Edit: I have added an "x" on each product on the list to remove them. I see the list, I add something (the list is not updated), I remove something and the list updates removing the element and showing the one I added! Looks like headers template is only being refreshed when actions are done on the template!

Thanks!





Reflection performance in Java or Spring

I'm transferring an old service written in Java to Spring. I noticed a significant drop in performance.I've identified that this code is responsible for it.The code below is called tens of thousands of times for objects.

Object helper = Class.forName(helperConfig.get(0)).newInstance();
((FieldHelperInterface) helper).setConnection(connection);
Method method = helper.getClass().getMethod(helperConfig.get(1), ResultSet.class);
value = method.invoke(helper, resultSet);

I know reflection is less efficient than direct calling, but why only after transferring to Spring? How to improve it? How to inject Spring "HelperInterface" components and call the methods indicated by their names?





How to store "types" and instantiate them dynamically in typescript?

I'm trying to accomplish a similar behavior that I can do with C#. In C# I can use reflection to dynamically instantiate a class based on the Type class. The following code shows how to do in c#, rather simple:

interface IHandler
{
   void Handle();
}
var handlers = new Dictionary<string, Type>
{
  { "querydom", typeof(QueryDomHandler) },
  { "other", typeof(OtherHandler) },
};

var type = handlers["querydom"];
var instance = (IHandler)Activator.CreateInstance(type, args);
instance.Handle();

How can I accomplish the same with typescript? I've sketched the following code, but I do not know how to get a "Type" from a class (QueryDomCommandHandler), or how to instantiate a class dynamically without using its name ( new QueryDomCommandHandler()).

let handlers = [];
handlers[CommandType.QueryDom] = QueryDomCommandHandler; //how to store the "type"?

chrome.runtime.onMessage.addListener((message: Command, sender, sendResponse) => {
    logger.debug(`${isFrame ? 'Frame' : 'Window'} '${document.location.href}' received message of type '${CommandType[message.command]}'`);
 
    const handlerType = handlers[CommandType.QueryDom];
    const handlerInstance = ????? //how to instantiate the class?
    if (message.command == CommandType.QueryDom) {
        const handler = new QueryDomCommandHandler(message as RulesCommand);
        const response = handler.handle();
        sendResponse(response);
        return true;
    }
    else if (message.command == CommandType.Highlight) {
        const handler = new HighlightCommandHandler(message as RulesCommand);
        handler.handle();
    }
});

Any insights?





mercredi 22 novembre 2023

how to use reflection to change non existing field in c#?

I have below code block and it should print 404 without using unsafe code or any changes to the Mutate method

const string constStr = "000";
Mutate(constStr);
var nonConst = "000";
Console.WriteLine(nonConst);  

static void Mutate(string str)
{
    
}```




Can I get a runnable get method from a class knowing the attribute using reflection? [duplicate]

Using reflection, following these examples, I can obtain the attributes and the methods of a class.

Now, given an object, I would like to take, for each attribute (let's say 'surname') of the given object, the associated value (the value of obj.getSurname()).

But I would like to do this at runtime, so I can't call the getSurname() getter method since I don't know that there is the 'surname' attribute.

One possibile idea is to get the attributes and methods of a class and, for each attribute, to search in the methods a method whose name starts with "get" and contains Capitalize(attribute.getName()).

Do you have any other idea to do this? Specifically, using reflection and given an attribute, can I directly obtain the getter method for that attribute?





What is the way of creating custom Reactive attribute?

I work with Reactive UI library for my WPF applications and was curious about how does the [Reactive] attribute work. I found out that there is nothing there in the attribute itself so there was a lot of questions about the actual work of it. Then I found the piece of code that loads current assembly (using Mono.Cecil and Fody libraries), finds all classes that extend ReactiveObject class and searches there for [Reactive] attributes (original source):

var reactiveObject = new TypeReference("ReactiveUI", "IReactiveObject", ModuleDefinition, reactiveUI);
var targetTypes = ModuleDefinition.GetAllTypes().Where(x => x.BaseType is not null && reactiveObject.IsAssignableFrom(x.BaseType)).ToArray();
var reactiveObjectExtensions = new TypeReference("ReactiveUI", "IReactiveObjectExtensions", ModuleDefinition, reactiveUI).Resolve() ?? throw new Exception("reactiveObjectExtensions is null");
var raiseAndSetIfChangedMethod = ModuleDefinition.ImportReference(reactiveObjectExtensions.Methods.Single(x => x.Name == "RaiseAndSetIfChanged")) ?? throw new Exception("raiseAndSetIfChangedMethod is null");
var reactiveAttribute = ModuleDefinition.FindType("ReactiveUI.Fody.Helpers", "ReactiveAttribute", helpers) ?? throw new Exception("reactiveAttribute is null");

Then is creates private field for each property and binds a method (that calls PropertyChanged event).
Everything was quite clear so I decided to create my own attribute and property resolver for the attribute but now I have an obvious problem. When the resolver changes the IL code - it should rewrite the current assembly (as I understand)). I don't know much about prebuilds and postbuild things but I think that this things should be done not in the already running assembly but somewhere in prebuild actions. Here is the code I actually wrote (it crushes on the module.Write(Assembly.GetExecutingAssembly().Location); line (quite obvious cause the current assembly file is locked)):

var module = ModuleDefinition.ReadModule(Assembly.GetExecutingAssembly().Location);
var reactiveResolver = new ReactivePropertyResolver()
{
    ModuleDefinition = module,
};
reactiveResolver.Execute();
module.Write(Assembly.GetExecutingAssembly().Location);
module?.Dispose();

I changed almoust nothing in the ReactivePropertyResolver, only some namespaces and other small things.

So the main question is - Whereand how should I do all this stuff to get it work?

(I've already asked the question on Software Engineering SE but got downvoted - quite curious :/ )





mardi 21 novembre 2023

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''object' does not contain a definition for 'Name''

Trying to solve this mistery! I have this dynamics structure that works only in some cases: This is where I mount the dynamic object

    string President { get; set; } = "Boss";
    string Name { get; set; } = "USA";
    int Population { get; set; } = 600000;
    Region[] Regions { get; set; }
    
    internal dynamic CreateRegion(dynamic req)
    {
        Regions = new Region[] { new("NY"), new("MI") };
            return new
  {
      Name,
      Population,
      Regions,
      President
  };
  
    
    }

this is where I consume my dynamic type:

var response = italy.CreateRegion(req);
Console.WriteLine(response);
Console.WriteLine(response.Name);
Console.WriteLine(response.Population);
Console.WriteLine(response.President);
foreach (var region in response.Regions)
{
    Console.WriteLine(region.Name.ToString());
}

The field Name is present in the object and I can see this. But When I try to call it, it returns the error:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''object' does not contain a definition for 'Name''

enter image description here enter image description here the tricky thing is that if I remove

Regions = Regions

, the from

return new
{
    Name = this.Name,
    Population = this.Population,
    Regions = Regions,
    Presindent = this.President,
};




How can I find all the types that have not inherited from anything in my code via Reflection in C#?

I have some classes that inherit from a base class and I have other classes that inherit from nothing:

public class SomeDerivedClass : BaseClass

and

public class FreeFromInheritanceClass
{
}

I want to find FreeFromInheritanceClass and other classes like it.

I tried this code but iI want to find FreeFromInheritanceClass and other classes like it.

I tried this code but it does not work:

typeof(Program)
.GetTypes()
.Where(i => i.BaseType == null)

I found out that my FreeFromInheritanceClass in fact inherits from System.Object.

So, how can I find the classes that do not inherit from anything?t does not work:

typeof(Program)
.GetTypes()
.Where(i => i.BaseType == null)

I found out that my FreeFromInheritanceClass in fact inherits from System.Object.

So, how can I find the classes that do not inherit from anything?





Can I cast a number into an enum, safely, with a fallback value?

I would like to write something like:

template <typename E, E fallback>
E safe_cast_to_enum(std::underlying_type_t<E> e);

which, for an enum class (or just an enum?) E, casts e to a corresponding value of E, if such a value exists, and to value fallback otherwise.

Can I do this generically?

Notes:

  • I suspect the answer is negative until at least C++20, but regardless - please (also) answer using the earliest C++ version with which this is possible.
  • If you like, you may assume fallback is a 'valid' value of the enum, i.e. it has an associated named identifier.

See also:





lundi 20 novembre 2023

How to register generic services with an interface using reflection

I have multiple services with this pattern, each repository class is using generics for the context and is implementing an interface also with generics:

public partial interface IUserRepository<TContext> : IRepository<TContext, UserRow> where TContext : DbContext
{
}

public partial class UserRepository<TContext> : RepositoryBase<TContext, UserRow>, IUserRepository<TContext> where TContext : DbContext
{
}

I could register my services manually but it's not scaleable as I will have dozens of them:

services.AddScoped<IUserRepository<DatabaseApiDbContext>, UserRepository<DatabaseApiDbContext>>();
services.AddScoped<IUserRepository<DatabaseApiDbContextSandbox>, UserRepository<DatabaseApiDbContextSandbox>>();

I think I could simplify the registration? I am not sure that would work, but something like this:

services.AddScoped(typeof(IUserRepository<>), typeof(UserRepository<>));

But that would still require a line of code for each repository.

Question

I would like to use reflection for registering my repositories. For example:

  1. Get all classes in my assembly that are inheriting the generics RepositoryBase class (e.g. XYZRepository<>)
  2. For each of these classes
  • Get the type for its corresponding Repository interface (e.g. IXYZRepository<>)
  • Register the XYZRepository<> class using the corresponding IXYZRepository<> interface

But I am not good enough with reflection to achieve that. Thanks for helping out!





dimanche 19 novembre 2023

Get activity Name from a superstructure

Here is my problem.

I successfully used a navigation drawer which overlays with no problems with EVERY activity in my App, modifying a template. There is a float button which I want to use like a pc F1 key, that sholud trigger a "help hint" or a "help screen" for the current activity.

To do that I obviously need the current activity. thing is if I use the classic reflection solution, all that i get back is class linked to the navigation menu overlay.

using debbuging i was searching for some... "property" like "child" or "active activity" or something like this, but i found none. The navigation overlays with no interference but has no information of what it is overlaying. Is there an hidden property?

Should i have to set a global variabile that i can retrieve where the float button is declared? i don't want to set helps buttons, everywhere T_T

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityDrawerProvaBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        //Comando che lega invoca il Navigation Drawer
        setSupportActionBar(binding.appBarDrawerProva.toolbar);
        binding.appBarDrawerProva.F1Touch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String mess = getApplicationContext().toString();
                Snackbar.make(view,mess, Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        DrawerLayout drawer = binding.drawerLayout;
        NavigationView navigationView = binding.navView;
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.

        //Qui dovrebbero aggiungersi i collegamenti alle finestre per ogni voce di menu???
        mAppBarConfiguration = new AppBarConfiguration.Builder(
                R.id.nav_home, R.id.reverse_Matrix, R.id.forma_standard)
                .setOpenableLayout(drawer)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_drawer_prova);
        NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
        NavigationUI.setupWithNavController(navigationView, navController);
    }

here is the code in which the action of the button should be triggered (his name is F1touch)

I know, as it this it can only get the context of which the button is declared, but i want the overlayed activity.

that's what i get in every activity

"easy" suggestion? --'





samedi 18 novembre 2023

Get Type of the properties of a data class Type in Kotlin

Let's say I have the following function in Kotlin

fun getPropertyTypes(dataClassType: Type): List<Type> {

}

And the Type of returnType is a data class in my project. How do I then get the Type of the properties of that data class?

data class ProjectDataClass(
    val pdPropertyResponse: MyResponseClass,
    val pdPropertyError: MyErrorClass,
)




How to implement a program that analyze an assembly with AssemblyLoadContext

I make test program to analyze information in assemblies using reflection.

Source code

using System.Reflection;
using System.Runtime.Loader;

var path = @"..\..\..\..\ClassLibrary1\bin\Debug\net8.0\ClassLibrary1.dll";
//var path = @"..\..\..\..\WebApplication1\bin\Debug\net8.0\WebApplication1.dll";
//var path = @"..\..\..\..\WpfApp1\bin\Debug\net8.0-windows\WpfApp1.dll";

var resolver = new AssemblyResolver(path);
var assembly = resolver.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(path)));

foreach (var type in assembly.GetTypes())
{
    System.Diagnostics.Debug.WriteLine(type.FullName);
}

public class AssemblyResolver : AssemblyLoadContext
{
    private AssemblyDependencyResolver resolver;

    public AssemblyResolver(string path)
    {
        resolver = new AssemblyDependencyResolver(path);
    }

    protected override Assembly? Load(AssemblyName assemblyName)
    {
        var assemblyPath = resolver.ResolveAssemblyToPath(assemblyName);
        return assemblyPath != null ? LoadFromAssemblyPath(assemblyPath) : null;
    }

    protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
    {
        var libraryPath = resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
        return libraryPath != null ? LoadUnmanagedDllFromPath(libraryPath) : IntPtr.Zero;
    }
}

Problem

The program works fine for class libraries.
However, for ASP.NET Core and WPF applications, Microsoft.AspNetCore.Mvc.Core and PresentationFramework cannot load the "System.Reflection.Re flectionTypeLoadException: 'Unable to load one or more of the requested types.'"

What I tried

Adding a FrameworkReference to the test program as follows will no longer cause an exception.

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <FrameworkReference Include="Microsoft.WindowsDesktop.App.WPF" />
  </ItemGroup>

However, this method cannot cope with unknown cases.

Question

How can we make it possible to load an assembly without adding a FrameworkReference to the test program?





jeudi 16 novembre 2023

call of reflect.Value.Interface on zero Value -

My code is like so:

val := reflect.ValueOf(v)

if val.Kind() == reflect.Ptr {
    val = val.Elem()
    v = val.Interface() // error arises here
}

I get this error:

call of reflect.Value.Interface on zero Value

anybody know why?





mercredi 15 novembre 2023

ILGenerator: How to get the value of the current object (owner) to call the ToString method

I have only recently started studying ILGenerator, so I will be glad of any explanations on this topic. Below is the code where there is a line to add the value of the current object (owner) to the stack:

MethodInfo debugLog = typeof(Console).GetMethod(nameof(Console.WriteLine),
   BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(object) }, null);

MethodInfo toString = GetType().GetMethod(nameof(ToString),
   BindingFlags.Public | BindingFlags.Instance);            

DynamicMethod setterMethod = new DynamicMethod("MyMethod", 
   MethodAttributes.Public, 
   CallingConventions.Standard, 
   null, 
   null, 
   typeof(TestClass), 
   true);

ILGenerator gen = setterMethod.GetILGenerator();

/*What code should I use?*/
/*gen.Emit(OpCodes.???);*/

gen.Emit(OpCodes.Call, toString);
gen.Emit(OpCodes.Call, debugLog);

gen.Emit(OpCodes.Ret);

setterMethod.Invoke(this, null);




Assembly.GetTypes() throws ReflectionTypeLoadException because of a protected abstract method

I'm trying to dynamically load assemblies and get the types in them, but I'm running into this exception:

System.Reflection.ReflectionTypeLoadException: 'Unable to load one or more of the requested types. Method 'HandleAuthenticateAsync' in type 'My.Namespace.Api.Attributes.BasicAuthenticationHandler' from assembly 'My.Namespace.API, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.'

This type inherits from the abstract class Microsoft.AspNetCore.Authentication.AuthenticationHandler, which has the abstract method: protected abstract Task<AuthenticateResult> HandleAuthenticateAsync();

I'm loading these assemblies from a separate dotnet 7 application - is there a way to load these assemblies in such a way that I can see non public types/fields/methods/etc through reflection? I also have access to the projects themselves, so I could build them with different settings if that's necessary.





Stuck at reflection in C# for a method with a list of long as its only parameter

I have this method in my TeacherBusiness.cs class:

public List<Teacher> GetList(List<long> ids)

I want to call it via reflection. This is what I do:

var ids = new List<long> { 1, 2, 3 }
var business = typeof(TeacherBusiness);
var getListMethod = business.GetMethod("GetList", new System.Type[] { typeof(List<long>) });
var entities = getListMethod.Invoke(business, new object[] { ids });

However, when I call it I get this error:

Object does not match target type.

I'm stuck at this point.

If I change the invoking code to getListMethod.Invoke(business, ids) the code won't compile and I get this error:

error CS1503: Argument 2: cannot convert from 'System.Collections.Generic.List' to 'object?[]?'

What should I do?





lundi 13 novembre 2023

Using reflection to filter on a many-to-many object property in EF Core

I am using EF Core to build a certain searching mechanism. I am providing a generic filter that is built in the front end like this for ex.: {"filter":{"logic":"and","filters":[{"field":"ObjectMaterial.MaterialId","value":"1","operator":"Eq"}, {"field":"ObjectMaterial.MaterialId","value":"2","operator":"Eq"}]},"sort":[],"take":20,"skip":0}

Now it is using reflection to build a LINQ query based on this filter, the problem now is that ObjectMaterial is a Collection based on the classes (simplified):

public partial class VwObjectOverview
{
    public int ObjectId { get; set; }
    public virtual ICollection<ObjectMaterial> ObjectMaterial { get; set; } = new List<ObjectMaterial>();
}
public partial class ObjectMaterial
{
    [Key]
    public int ObjectMaterialId { get; set; }

    public int MaterialId { get; set; }
}

Whenever trying to filter based on the MaterialId, the program wont run and gives errors some way or another. The code below is where I am at right now. I want to achieve a LINQ query like this: ctx.VwObjectOverview.Where(o => o.ObjectMaterial.Any(om => om.MaterialId == 1 && om.MaterialId == 2)) for ex

    public static class QueryableExtensions
    {
        public static async Task<(IQueryable<TEntity> query, int count)> SearchWithFilter<TEntity>(this IQueryable<TEntity> query, List<SortDefinition>? sort = null, FilterDefinition? filter = null, int? skip = null, int? take = null)
        {
            if (filter != null && filter.Filters.Count > 0 && (filter.Field == null || filter.Value == null))
            {
                Expression<Func<TEntity, bool>> filterExpression = BuildFilterExpression<TEntity>(filter);
                query = query.Where(filterExpression);
            }

            var count = await query.CountAsync();

            if (sort != null)
            {
                foreach (SortDefinition sortDefinition in sort)
                {
                    var parameter = Expression.Parameter(typeof(TEntity));
                    var property = Expression.Property(parameter, sortDefinition.Field);
                    var propAsObject = Expression.Convert(property, typeof(object));
                    var lambda = Expression.Lambda<Func<TEntity, object>>(propAsObject, parameter);
                    query = sortDefinition.Dir == SortDirection.Asc
                        ? query.OrderBy(lambda)
                        : query.OrderByDescending(lambda);
                }
            }

            if (skip.HasValue)
            {
                query = query.Skip(skip.Value);
            }

            if (take > 0)
            {
                query = query.Take(take.Value);
            }

            return (query, count);
        }

        private static Expression<Func<T, bool>> BuildFilterExpression<T>(FilterDefinition filterDef)
        {
            var type = typeof(T);
            var parameter = Expression.Parameter(type);
            Expression filterExpr = BuildFilterExpression<T>(filterDef, parameter);
            return Expression.Lambda<Func<T, bool>>(filterExpr, parameter);
        }

        private static Expression BuildFilterExpression<T>(FilterDefinition filterDef, Expression parameter)
        {
            if (filterDef.Filters != null && filterDef.Filters.Any())
            {
                // Build a nested filter expression by recursively calling this method on each nested filter
                var filterExpressions = filterDef.Filters
                    .Select(nestedFilterDef => BuildFilterExpression<T>(nestedFilterDef, parameter))
                    .ToArray();

                return filterDef.Logic == FilterLogic.And
                    ? filterExpressions.Aggregate(Expression.AndAlso)
                    : filterExpressions.Aggregate(Expression.OrElse);
            }

            if (filterDef.Field == null || filterDef.Value == null)
                return parameter;

            // Split the field into parts if it contains a dot (indicating a related entity property)
            var fieldParts = filterDef.Field.Split('.');
            Expression propertyExpr = GetPropertyAccessExpression(parameter, fieldParts);

            //Expression valueExpr = Expression.Constant(Convert.ChangeType(filterDef.Value, propertyExpr.Type));
            var convertedValue = Convert.ChangeType(filterDef.Value, propertyExpr.Type);
            Expression valueExpr = Expression.Constant(convertedValue);


            valueExpr = Expression.Convert(valueExpr, propertyExpr.Type);
            switch (filterDef.Operator)
            {
                case FilterOperator.Eq:
                    return Expression.Equal(propertyExpr, valueExpr);
                default:
                    throw new NotSupportedException($"Filter operator {filterDef.Operator} is not supported.");
            }
        }

        private static Expression GetPropertyAccessExpression(Expression parameter, string[] fieldParts)
        {
            Expression propertyAccess = parameter;

            foreach (var fieldPart in fieldParts)
            {
                // If the property is a collection, use Any to check if any element satisfies the condition
                if (propertyAccess.Type.IsGenericType && propertyAccess.Type.GetGenericTypeDefinition() == typeof(ICollection<>))
                {
                    var elementType = propertyAccess.Type.GetGenericArguments()[0];
                    var elementParameter = Expression.Parameter(elementType);
                    var elementProperty = Expression.PropertyOrField(elementParameter, fieldPart);

                    // Create a predicate to use with Any
                    var predicate = Expression.Lambda(
                        BuildFilterExpression<object>(new FilterDefinition
                        {
                            Field = fieldPart,
                            Value = null, // You might need to adjust this depending on your use case
                            Operator = FilterOperator.IsNotNull
                        }, elementParameter),
                        elementParameter);

                    // Use Any to check if any element satisfies the condition
                    propertyAccess = Expression.Call(
                        typeof(Enumerable),
                        "Any",
                        new[] { elementType },
                        propertyAccess,
                        predicate);
                }
                else
                {
                    // Access the property in the usual way
                    propertyAccess = Expression.PropertyOrField(propertyAccess, fieldPart);
                }
            }

            return propertyAccess;
        }
    }




How does Unity auto-detect public members for serialization?

I'm making a custom C++ game engine, and I'd like to do something similar to what Unity does by auto-serializing public members of MonoBehavior classes, which subsequently allows for the member to be drawn in the editor (ImGui, in my case).

My question is: how does Unity actually do this auto-detection? It seems like this feature is closely tied to reflection, but at least with the C++ reflection libraries that I've looked at, it seems that you have to manually "register" your members for iteration later on.

How does Unity do this without the user of the class having to do any manual registration?

I've researched C++ reflection libraries, specifically RTTR and Meta. Both of them require manual registration of class data members.





dimanche 12 novembre 2023

Check at runtime whether a class is part of the code or part of one of the dependencies

I am working on an engine which uses the Java Reflect library to get methods of classes and their super classes. For the analysis, I need to know which of the methods are inherited by a super class, and whether the super class is part of one of the libraries or if the class is part of the project itself. Is there any way to determine this?

I tried to use the classloader, but I either don't know which is the correct way of doing so or it doesn't work (what I rather think), cause the classloader can also load classes of the dependency.

Furthermore, it can be the case that a project has many modules as well as packages, which makes it (in my opportunity, but maybe I'm wrong) impossible to use the package, which the class is part of.





samedi 11 novembre 2023

How do I retrieve all classes from a package in the neatest way possible?

First off, I want to say that I read this StackOverflow post

My current understanding is that if you want to get all classes from a package without writing a ton of code lines, you are basically stuck with the Reflections API. Here are some of the options:

Option 1.

    private static Set<Class<?>> getClassesFromPackage(String packageName) {
        Reflections reflections = new Reflections(packageName, new SubTypesScanner(false));
        return new HashSet<>(reflections.getSubTypesOf(Object.class));
    }

Not optimal: SubTypesScanner is deprecated so you'll get a warning

Option 2.

    private static Set<Class<?>> getClassesFromPackage(String packageName) {
        Reflections reflections = new Reflections(packageName, Scanners.SubTypes.filterResultsBy(s -> true));
        return new HashSet<>(reflections.getSubTypesOf(Object.class));
    }

Not optimal: Scanners.SubTypes.filterResultsBy(s -> true) is clumsy AF so you either get code that is not easily readable or you have to provide some meta commentary

    private static Set<Class<?>> getClassesFromPackage(String packageName) {
        Reflections reflections = new Reflections(packageName, getStuffThatMakesItWork());
        return new HashSet<>(reflections.getSubTypesOf(Object.class));
    }

    private static Scanners getStuffThatMakesItWork() {
        return Scanners.SubTypes.filterResultsBy(s -> true);
    }

Wouldn't it be peachy if I could write just this

    private static Set<Class<?>> getClassesFromPackage(String packageName) {
        Reflections reflections = new Reflections(packageName);
        return new HashSet<>(reflections.getSubTypesOf(Object.class));
    }

It is so much more readable, but sadly it doesn't work (the returned set would contain zero items)

What is the best way to scan for package classes?

Criteria:

  1. The code should be as short as possible.
  2. The code should be readable (a random person shouldn't get any WTF moments when looking at it)
  3. You shouldn't get warnings

One thing I haven't mentioned yet is that the whole Reflections library is not maintained since 2021 so it may not be a solid long-term solution to rely on it. Are there alternatives that are at least just as good?





How does boost pfr get the names of fields of a struct?

In Boost 1.84 (currently in progress):

Big new feature: field names reflection. Added new constexpr boost::pfr::get_name<N, T>() function that returns a std::string_view with a name of field at index N of an aggregate T. Requires C++20.

Using the latest version of pfr on github, you can write code like

#include <boost/pfr/core.hpp>
#include <boost/pfr/core_name.hpp>

struct S
{
    int i = 1;
    double d = 2;
    std::string s = "three";
};

const S s;
constexpr auto names = boost::pfr::names_as_array<S>();
boost::pfr::for_each_field(
    s,
    [&names](const auto& field, std::size_t idx)
    { std::cout << idx << ": " << names[idx] << " = " << field << '\n'; });

Output:

0: i = 1
1: d = 2
2: s = three

How does this work? This blog post explains how aggregate initialization can be repurposed to get the fields, but getting the field names seems like magic! But I get the above output on the big three compilers (latest Visual C++, gcc 13.2, clang 16). I'm no wiser looking at the code in core_name20_static.hpp.





vendredi 10 novembre 2023

.NET Core 7 Dynamic Component using reflection

I have one parent .razor component and one child and in the child I load a dynamic component with parameters.... all ok so far it loads and I can retrieve data from the DB. My issue is I need to call a method in the DynamicComponentFooter1 called "Update" when I click the update button.

Picture.razor (Parent)

<AMS.Resources.UI.Pages.Picture.Picture_Base @ref="Picture"
DynamicComponentFooter1="@DynamicComponentFooter1" DynamicComponentFooter1Parameters="@DynamicComponentFooter1Parameters" />

[Parameter] public Type? DynamicComponentFooter1 { get; set; }
[Parameter] public Dictionary<string, object>? DynamicComponentFooter1Parameters { get; set; }

Picture.razor.cs (I create the dynamic component called Picture_Membership)

this.DynamicComponentFooter1Parameters = new Dictionary<string, object>();

this.DynamicComponentFooter1Parameters.Add("UserCurrentClassName", "Picture_Membership");
this.DynamicComponentFooter1Parameters.Add("UserCurrentAction", "view");
this.DynamicComponentFooter1Parameters.Add("PictureID", "1");

this.DynamicComponentFooter1 = typeof(AMS.Resources.UI.Pages.Picture_Membership.Picture_Membership_Base);

Up till now all ok, but when i click the Update button in the parent I need to call the Update method in the dynamic control also either by reflection or any other way. The normal way would be to add a @ref="Picture_Membership" tag and call Picture_Membership.Update(); but I don't see a way I can add this as I am sending in the dynamic control.

Update Method is async Task:

public async Task<bool> Update()
{
    return true;
}

I dont see a way I can add a @ref tag so have tried the following:

var methodInfo = this.Picture.DynamicComponentFooter1.GetMethod("Update");

Type[] typeArgs = { typeof(Task<bool>) };
var genericMethodInfo = methodInfo.MakeGenericMethod(typeArgs);

var result = genericMethodInfo.Invoke(null, new object[]{});

But I get the following error:

An exception of type 'System.InvalidOperationException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'System.Threading.Tasks.Task`1[System.Boolean] Update() is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true.'

enter image description here

What am I doing wrong?

Any help would be greatly appreciated :)





how to parse a function from a text or excel file

In several apps, i call functions from an excel cell or a text file. example of cells where i call my functions

My issue is : all my functions are written in the same c# class. .cs where all my functions are written

How do i better this architecture ? My functions are parsed, then trigger actions on the world in those fonctions. But I would like to arrange them in many classes, grouped by the type of actions ( time, movement, text etc... ) but have no idea how to write any of this.

I try to be consise because de problem is kind of blurry to me I could't phrase it otherwise. If it implies a whole new architecture, and big changes on the way everything is written, I'm all the more curious !

Thanks !

I tried using MethodInfo and System.Reflection to parse types and function names. but the way my functions are written is to make it the most simple (enable(_item), wait(0), move(right)) so i don't have many info of what type if function i parse.





In Kotlin, can I access the known 'when' clause values?

I have a few instances of this sort of code:

enum class Cat { Fat, Greedy, Sleepy, Lasagna }
...
when (cat) {
    Fat -> // do fat
    Greedy -> // do greedy
    else -> throw RuntimeException("You have a $cat cat - I don't know about those.")
}

I would like it to say "You have a $cat cat - I only know about Fat and Greedy" but I don't want to have to update the message when I add a new clause.

  • Is there any way to read the options known by a 'when' clause? (I suspect not, but Kotlin is endlessly surprising.)

I don't want to decorate the enum with flags that need to be kept up to date with the when clause, nor add lambdas to the enum, to turn this when clause into dispatch-based logic.

Thanks.





Comparing characteristics of accessing class properties in C# via a static generic class and static class with ConcurrentDictionary

I'm using C#, and I have two approaches for accessing class properties: through Entity<Unit>.PropertyAccessors and EntityManager.PropertyAccessor<Unit>(). Both options provide access to class metadata for working with properties. I'm interested in the differences in their performance, memory usage, thread safety, and other relevant aspects.

What are the key distinctions between Entity<Unit>.PropertyAccessors and EntityManager.PropertyAccessor<Unit>() in terms of performance, memory usage, thread safety, and other critical aspects? Is there a preferred option in each of these categories? Are there any potential pitfalls or gotchas that I should be aware of when using either of these implementations?

I'm using a ThreadSafeDictionary with ConcurrentDictionary<TKey, Lazy<TValue>> under the hood.

Below is the code I'm using for a more detailed context:

using System.Reflection;
using System.Linq.Expressions;

internal sealed record PropertyAccessor(string Name, Func<object, object> Get, Action<object, object> Set);

internal static class Entity<TEntity> where TEntity : class, IEntity
{
    public static IEnumerable<PropertyAccessor> PropertyAccessors => LazyPropertyAccessors.Value;

    private static readonly Lazy<IList<PropertyAccessor>> LazyPropertyAccessors = new(() => GetPropertiesAccessor(typeof(TEntity)));

    private static IList<PropertyAccessor> GetPropertiesAccessor(IReflect type)
    {
        return type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
            .Where(p => p.CanRead && p.CanWrite)
            .Select(GetEntityProperty)
            .ToArray();
    }

    private static PropertyAccessor GetEntityProperty(PropertyInfo property)
    {
        return new PropertyAccessor(property.Name, property.GetGetMethod().BuildGetAccessor(), property.GetSetMethod().BuildSetAccessor());
    }
}

internal static class EntityManager
{
    private static readonly IThreadSafeDictionary<Type, IEnumerable<PropertyAccessor>> EntitiesPropertiesAccessor;

    static EntityManager()
    {
        EntitiesPropertiesAccessor = new ThreadSafeDictionary<Type, IEnumerable<PropertyAccessor>>();
    }

    public static IEnumerable<PropertyAccessor> PropertiesAccessor<TEntity>() where TEntity : class, IEntity
    {
        return EntitiesPropertiesAccessor.GetOrAdd(typeof(TEntity), GetPropertiesAccessor);
    }

    private static IEnumerable<PropertyAccessor> GetPropertiesAccessor(IReflect type)
    {
        return type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
            .Where(p => p.CanRead && p.CanWrite)
            .Select(GetEntityProperty)
            .ToArray();
    }

    private static PropertyAccessor GetEntityProperty(PropertyInfo property)
    {
        return new PropertyAccessor(property.Name, property.GetGetMethod().BuildGetAccessor(), property.GetSetMethod().BuildSetAccessor());
    }
}


public static class ReflectionTypeExtensions
{
    public static Func<object, object> BuildGetAccessor(this MethodInfo method)
    {
        if (method == null)
            throw new ArgumentNullException(nameof(method));

        var declaringType = method.DeclaringType;

        if (declaringType == null)
            throw new NullReferenceException(nameof(method.DeclaringType));

        var obj = Expression.Parameter(typeof(object));

        var getter = Expression.Lambda<Func<object, object>>(
            Expression.Convert(Expression.Call(Expression.Convert(obj, declaringType), method), typeof(object)),
            obj);

        return getter.Compile();
    }

    public static Action<object, object> BuildSetAccessor(this MethodInfo method)
    {
        if (method == null)
            throw new ArgumentNullException(nameof(method));

        var declaringType = method.DeclaringType;

        if (declaringType == null)
            throw new NullReferenceException(nameof(method.DeclaringType));

        var obj = Expression.Parameter(typeof(object));
        var value = Expression.Parameter(typeof(object));

        var expr = Expression.Lambda<Action<object, object>>(Expression.Call(Expression.Convert(obj, declaringType),
                method,
                Expression.Convert(value, method.GetParameters()[0].ParameterType)),
            obj,
            value);

        return expr.Compile();
    }
}




Golang Reflect Methods for Any type

I have been banging my head against this for a couple days now.

My goal is to have a function like so:

func ListFuncs(x any) []string {
    inst := reflect.New(reflect.TypeOf(x))
    y := inst.Elem().Interface()

    t := reflect.TypeOf(y)
    var s []string
    for i := 0; i < t.NumMethod(); i++ {
        s = append(s, t.Method(i).Name)
    }

    return s
}

I know the above code doesn't make FULL sense, but I have been changing it non-stop, it should give a basic idea of what I WANT to do, but I cannot for the life of me list functions for "any". I cant even make it work when I case it to the class I KNOW it is.

I can only make it work when I do reflect.TypeOf(StructName{}) is this even possible to do without explicitly knowing the struct used or having a switch statement for all the possible structs?





mercredi 8 novembre 2023

System.OutOfMemoryException .NET 4.8 WPF App

I'm working on a WPF (WCF architecture) app. This app has 2 main solutions, the client(front end) and the controller(back end), the way the client communicates with the back end is through reflective calls, in essences it builds up a XML doc containing info like the method to execute, the namespace that the method is in and method args etc...

So this specific method is to upload documents. It works perfectly until the file is > 1GB in size. The error occurs when the client builds up the XML doc for the reflective call.

We add to the XML doc like this:

result.Add(new XElement(itemProperty.Name, new XCData(data)));

In this case the itemProperty.Name is the method name and the XCData is the method args. So the doc to upload will obvisolsy be the arguments, we receive it in a byte[]. And we need to pass it to the XCData constructor as a string, so the following is used:

string data= Convert.ToBase64String((byte[])value)

Note that this works with smaller files but with the 1GB file a 'System.OutOfMemoryException' exception is thrown when trying to convert the byte[] to base64String.

I have tried reading the array in chunks, but when calling the stringBuilder.ToString(), the same exception is thrown...

 public static string HandleBigByteArray(byte[] arr)
        {
            try
            {
                
                #region approach 2
                int chunkSize = 104857600;//100MB
                StringBuilder b64StringBuilder = new StringBuilder();
                int offset = 0;

                while (offset < arr.Length)
                {
                    int remainingBytes = arr.Length - offset;
                    int bytesToEncode = Math.Min(chunkSize, remainingBytes);
                    string base64Chunk = Convert.ToBase64String(arr, offset, bytesToEncode);
                    b64StringBuilder.Append(base64Chunk);
                    offset += bytesToEncode;
                }


                return b64StringBuilder.ToString();
                #endregion
            }
            catch (Exception)
            {
                throw;
            }
        }

I have no idea what to do or how to further debug/approach this..





Get a dictionary of a generic type based on a runtime value

I wish to declare a dictionary based on a runtime type. So, instead of doing this:

IEnumerable dict = null;
if(type == typeof(SomeType)) dict = new Dictionary<SomeType, string>()
if(type == typeof(SomeOtherType)) dict = new Dictionary<SomeOtherType, string>()

I wish to do something like this:

IEnumerable dict = new Dictionary<type, string>();

How can I achieve this? Also, I would like to be able to call a different method with just the type of the dictionary in one of these ways:

var result = SomeMethod(typeof(Dictionary<type, string>));
var result = SomeMethod<Dictionary<type, string>>();

EDIT: extra context:

I get the types from a different API call as strings. Then I use reflection to get the types by AssemblyQualifiedName, which results in a List to execute the calls with. Based on the name of these types, REST endpoints need to be called.

If (type == SomeType) httpClient.GetAsync("SomePath/{SomeType.Name}")

This endpoint returns a Dictionary<SomeType, string>. To be able to deserialize these types, I need to call something like

httpClient.GetAsync<Dictionary<type, string>>("SomePath/{SomeType.Name}")

Otherwise an exception will occur in the System.Text.Json package.





mardi 7 novembre 2023

find another method in same class from its attribute value and invoke

I am trying to make this HandlerEvent to run methods original handler unless there is legacy defined on its SimpleAttribute then instead run legacy method. thanks for your help in advance

public static class Extensions
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method)]
    public class SimpleAttribute : Attribute
    {
        public string Name { get; set; }
        public string Legacy { get; set; }
    }
}

public static async Task HandleEvent<T>(Func<T, Task> handler)
{
    var legacy = handler.Method.GetCustomAttribute<SimpleAttribute>().Legacy;

    if(legacy == null)
       await handler();
    else
    {
        var type = typeof(T).Assembly.GetTypes().Where(t => t.Namespace == handler.Method.DeclaringType.Namespace);
        var methodInfo = type.GetMethod(legacy);
        methodInfo.Invoke(o, parameters);
    }
}

public class Boo
{
   [Simple(Name = "FlagName")]
   public async Task Foo_OLD()
   {

   }

   [Simple(Name = "FlagName", Legacy= "Foo_OLD")]
   public async Task Foo()
   {

   }
}




Inspecting recursive function with decorator fails only in Unittest

I have a recursive function that I would like to decorate. This decorator uses inspect.getclosurevars. The decorator fails and raises ValueError: cell is empty but only when used on functions definied in Unittest. When used outside they work as expected, where the recursive function is part of getclosurevars.unbound.

Minimal example:

import inspect
def deco(f):
    v = inspect.getclosurevars(f)
    print(v)
    return f

@deco # does not error
def recursive(n):
    if n <= 0 : return n
    return recursive(n-1)

import unittest
class TestA(unittest.TestCase):

    def test_but_in_unittest(self):
        
        @deco # ValueError: cell is empty
        def another_recursive(n):
            if n <= 0: return n
            return another_recursive(n-1)


unittest.main()

I’m really at a loss, initially I thought it was common for all recursive functions, but after some more testing and asking, I realized the error was occurring only within the test case.

I would normally expect the unittest testcase to behave the same as if it was ‘plain code’…





lundi 6 novembre 2023

How do we set a dictionary using reflection if we don't know the type arguments during compile-time?

We have a dictionary in some unknown class, Dictionary<TKey, TValue> MyDictionary and we have the FieldInfo object obtained using reflection. We also have the type arguments Type keyType = typeof(TKey) and Type valueType = typeof(TValue) which are obtained during runtime.

The key-value pairs are present in two separate lists List<object> keys and List<object> values.

How do we generate the dictionary and set its value using FieldInfo.SetValue()?

So far, we tried this:

var dictionary = Activator.CreateInstance(fieldInfo.FieldType);
var keys = new List<object>();
var values = new List<object>();
// Code to set keys and values
for (int i = 0; i < keys.Count; i++)
   (dictionary as IDictionary).Add(keys[i], values[i]);

fieldInfo.SetValue(mainObj, dictionary);

In specific case where TValue is List<int>, the add statement throws an exception

System.ArgumentException: 'The value "System.Collections.Generic.List1[System.Object]" is not of type "System.Collections.Generic.List1[System.Int32]" and cannot be used in this generic collection.





Create Scala case classes for SCIO type safe read/write dynamically

I'm trying to generate Scala classes dynamically, which then should be used as safe types in SCIO read/write to/from GCP BigQuery.

Target example:

import com.spotify.scio.bigquery._
import com.spotify.scio.bigquery.types.BigQueryType

@BigQueryType.fromTable("dataset.SOURCE_TABLE")
class SOURCE_TABLE

@BigQueryType.toTable
case class TARGET_TABLE(id: String, name: String, desc: String)

def main(cmdlineArgs: Array[String]): Unit = {
  val (sc, args) = ContextAndArgs(cmdlineArgs)
  sc.typedBigQuery[SOURCE_TABLE]()  // Read from BQ
    .map( row => transformation(row) ) // Transform -> SCollection[TARGET_TABLE]
    .saveAsTypedBigQueryTable(Table.Spec(args("TARGET_TABLE")))  // save to BQ
  sc.run()
  ()
}

As as input there are dataset, SOURCE_TABLE, TARGET_TABLE, list of target fields, so I can build up a string source of generated classes. All these values are retrieved dynamically from other 3rd party (json, xml, etc. ) and can be mutable by every execution.

So, the source of generated classes can be presented as:

val sourceString =
  s"""
     |import com.spotify.scio.bigquery.types.BigQueryType
     |
     |@BigQuery.fromTable("$dataset.$SOURCE_TABLE")
     |class $SOURCE_TABLE
     |
   """.stripMargin

val targetString =
  s"""
     |import com.spotify.scio.bigquery.types.BigQueryType
     |
     |@BigQueryType.toTable
     |case class $TARGET_TABLE($fieldDefinitions)
   """.stripMargin

These sources are considered to be translated to classes, which types are required for SCIO BigQuery I/O.

Scala version: 2.12.17

I tried to use Scala runtime Mirror and Toolbox (from this answer, from this, etc.). But all variants throw the same error: enable macro paradise (2.12) or -Ymacro-annotations (2.13) to expand macro annotations It's obvious that the Toolbox's internal compiler doesn't see the build.sbt settings:

addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full)

Besides that here mentioned that Toolbox is not intended for such complex thing.

So, I decided to apply an approach using the package scala.tools.nsc as described in this answer. But it throws the same error about the lack of macro annotations.

Thus the main question: is there any chance to add required compiler plugin settings to scala.tools.nsc.{Global, Settings} or to apply any other approach to generate such annotated classes dynamically?

def compileCode(sources: List[String], classpathDirectories: List[AbstractFile], outputDirectory: AbstractFile): Unit = {
  val settings = new Settings
  classpathDirectories.foreach(dir => settings.classpath.prepend(dir.toString))
  settings.outputDirs.setSingleOutput(outputDirectory)
  settings.usejavacp.value = true
  //*****
  // Add macros paradise compiler plugin?
  //*****
  val global = new Global(settings)
  val files = sources.zipWithIndex.map { case (code, i) => new BatchSourceFile(s"(inline-$i)", code) }
  (new global.Run).compileSources(files)
}




dimanche 5 novembre 2023

Why can't I use a lamda expression when calling Constructor.newInstance()?

I am trying to instantiate an object using Constructor.newInstance. The constructor requires one argument of type DoubleSupplier. This is successful if I first create a DoubleSupplier object, then pass the object to the newInstance method:

DoubleSupplier  supplier    = () -> 3.0;
obj = ctor.newInstance( supplier );

But if I try using the lamda directly in the newInstance invocation:

obj = ctor.newInstance( () -> 3.0 );

it fails to compile with "The target type of this expression must be a functional interface." What is the difference between the two methods?

Incidentally, I can use the lambda when instantiating an object using "new".

obj2 = new SubTypeA( () -> 3.0 );

Sample program follows.

public class CtorDemo
{
    public static void main(String[] args)
    {
        SuperType   obj = getSubType( SubTypeA.class );
        System.out.println( obj.getClass().getName() );
    }
    
    private static SuperType 
    getSubType( Class<? extends SuperType> clazz )
    {
        SuperType   obj = null;
        try
        {
            Constructor<? extends SuperType> ctor    =
                clazz.getConstructor( DoubleSupplier.class );
            
            DoubleSupplier  supplier    = () -> 3.0;
            obj = ctor.newInstance( supplier );
            // obj = ctor.newInstance( () -> 3.0 );
            // compile error
        }
        catch ( NoSuchMethodException
                | InvocationTargetException 
                | IllegalAccessException 
                | InstantiationException exc )
        {
            exc.printStackTrace();
            System.exit( 1 );
        }
        return obj;
    }

    private static class SuperType
    {
    }
    private static class SubTypeA extends SuperType
    {
        public SubTypeA( DoubleSupplier supplier )
        {
        }
    }
}




samedi 4 novembre 2023

How can I skip fields of certain types during serialization?

I have a Spring AOP service which intercepts a lot of different third-party controllers endpoints. My service runs an endpoint, gets the result DTO, serialize DTO to json with ObjectMapper, sends json to Kafka and return the DTO outside. The problem is: the service shouldn't serialise fields of particular types (e.g MultipartFile). I can't use @JsonIgnore annotation, because DTO should be returned outside without changes. Can I make ObjectMapper skip fields of certain types? Or, maybe, copy the DTO and set this fields to null with reflection?





vendredi 3 novembre 2023

From a 700MB json file, how do I list all the keys in Powershell?

I tried

$obj = [System.IO.File]::ReadLines((Convert-Path -LiteralPath names.json)) | ConvertFrom-Json
 
$keys = @() 
 
foreach ($key in $obj.GetEnumerator()) { 
  $keys += $key.Key 
} 
 
Write-Output $keys

But after over 24 hours it had not completed.

I need the key names so I can

  1. Delete irrelevant info and make it smaller
  2. Convert it to csv (the key names are required, otherwise PS just uses the first object and ignores keys which are not present in the first object)

The JSON is a version of this one (though 200 megs smaller): https://kaikki.org/dictionary/All%20languages%20combined/by-pos-name/kaikki_dot_org-dictionary-all-by-pos-name.json





jeudi 2 novembre 2023

DotNet: Is there a newer, better, better maintained alternative to ReactiveX?

Reactive Extensions saved me lots of hours (even months) of coding time, but it seems to become out of focus. So I am looking for an alternative. I don't need fancy cross-language communication, nor do I need JS support or whatnot. Just a simple, easy-to-use abstraction of IObserver/IObservable that uses attributes.

As always, thanks tons!





mercredi 1 novembre 2023

getting all export type info using reflection for golang package

Project structure is like below


root
/ package1
executor struct
/ package2
model struct

inside package1 want to programmatically read all exported types of package2. I believe it is doable using reflection. Facing issue in finding the import path of package2.

Tried using https://pkg.go.dev/go/importer#pkg-functions importer package using

pkg:= importer.Default().Import("model") this does not work.

Tried using PkgPath

pkgPath := reflect.TypeOf(model.Policy{}).PkgPath()
cfg := &packages.Config{
        Mode:  packages.NeedTypes | packages.NeedTypesInfo,
        Tests: false,
        Env:   append(os.Environ(), "GO111MODULE=off", "USE_SYSTEM_GO=1",
    }
pkgs, err := packages.Load(cfg, pkgPath) 
pkg:= importer.Default().Import("model") this does not work.

this also does not work.

This is bazel based build system.





lundi 30 octobre 2023

How to inject a method into a class at runtime without ASM?

In past versions of the bytecode manipulation framework Mixin, there was a method called prepareConfigs(MixinEnvironment). A nonstandard, but very commonly-used, way to bootstrap Mixins at a certain phase of the lifecycle was to access and call that method using Reflection.

In later versions of the framework, that method's signature has been changed to prepareConfigs(MixinEnvironment, Extensions), causing the Reflection-based usages to break.

The owner of the library has made it clear that breaking this was intentional and will not allow a fix. However, even though it was bad practice to use that strategy, the usage was common enough that end-users are unable to use many apps that relied on the framework.

I would like to make a compatibility patch that adds the old method back to the class to stop the crashes. Problem is, this requires injecting a method into a class that is restricted from being transformed by ASM.

The only requirement is that the method does not throw a NoSuchMethodException when accessed via reflection, since I'm easily able to implement their intended behavior somewhere else. It doesn't actually need to do anything, it just needs to stop the exception from being thrown.

I've heard people offhand-mention a way to declare class members that can only be accessed by Reflection, but I couldn't find any details on it.

Is there a way to do what I need without ASM?





dimanche 29 octobre 2023

Type Load Exception On Method Load

I have a Visual Studio 2023 solution containing 32 projects. The projects extensively reference each other. 31 of the projects are class libraries, while the last one is a console application used whenever I want to test one of the functions in my library, so I don't have to create a new temporary one each time. Visual Studio's Immediate Window has never worked for me, even before this issue. All the projects are written in C# 11, and use .NET 7.0. Many of the projects reference the NuGet package System.Collections.Immutable.

I was attempting to write a Crawler, like a Web Crawler, but for types. It would iterate though all static/nonstatic members of a type, add their parameter types and return types (if present) to a HashSet<Type>. It would then recursively do the same for each type that was added. It was designed so that it would only ever iterate though each time once.

It did this by creating a List<Type>, and every time a type was added to the HashSet<Type> that did not already exist, it would add it to the list. After the list was complete, it would recursively do the same for each type in the list. If a type was, or contained in its generic parameters (if present), a generic parameter, it would be substituted with its definition. There were also some functions to cover pointers, references, and arrays.

I ran the function on an object, and it worked fine. I got the type for the object using C#'s typeof(?) method. However, then I ran the function on a static class in one of my projects, and it threw an exception.

At this point, it is worth mentioning the projects that are involved with this. I have one console application project (Test) in which I am executing the crawler in a second project (Brendan.IC.Typed.Execution), which was supposed to crawl through a static class in a third project (Brendan.IC.Typed). The latter project references System.Collections.Immutable. System.Collections.Immutable most likely has nothing to do with this, but I think its worth mentioning everything, since I have absolutely no idea what the problem is.

The exception was a System.TypeLoadException.

System.TypeLoadException: 'Could not load type 'Brendan.IC.Typed.TypedEvolutionLookup`1' from assembly 'Brendan.IC.Typed, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.'

The static class I had called the crawler on was Brendan.IC.Typed.TypedEvolution. One of its static methods contained a parameter of type Brendan.IC.Typed.TypedEvolutionLookup<>. This is how the crawler found it. It then was unable to load it. The exception was thrown in the MethodInfo.GetParameters() function.

Initially, I assumed this was some problem with my crawler function. I cleaned and rebuilt the solution, my normal first step in handling errors, but to no effect. I recompiled the solution multiple times in both Debug and Release mode, to no effect. I checked my code for anything that might effect type loading. I found nothing. Finally, I decided to load the offending type in my top-level statements. It threw an exception, the same exception it had previously.

System.TypeLoadException: 'Could not load type 'CodeInterpretation.Typed.TypedEvolutionLookup`1' from assembly 'Brendan.IC.Typed, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.'

Here was my top-level statement:

using Brendan.IC.Typed;
using Brendan.IC.Typed.Execution;
using static System.Console;
Type bigType = typeof(TypedEvolutionLookup<int>);
Crawler.Crawl(bigType);
ReadKey(true);

I simplified it to this:

using Brendan.IC.Typed;
using static System.Console;
Type bigType = typeof(TypedEvolutionLookup<int>);
ReadKey(true);

This is when things started to get weird... real weird.

First of all, I noticed that there was no line number or call stack associated with the exception.

A picture of the exception.

Upon selecting Show Call Stack:

A picture of the call stack.

Here's my full screen:

A fullscreen screenshot of the exception.

Usually, when I get an exception, I can add a WriteLine() right before the line I suspect, and it will print to the console before the program terminates due to the exception. I did so, and added a breakpoint on the same line, intending to step through the program. Finally, I added a generic parameter to the generic type definition. But the program didn't even hit the breakpoint! Nor did it print to the console!

New code:

using Brendan.IC.Typed;
using static System.Console;
WriteLine("hi");
Type bigType = typeof(TypedEvolutionLookup<int>);
ReadKey(true);

Screenshot:

Screenshot of exception.

I put it in release mode, too. As expected, it did not throw an error, since it optimized out the unnecessary assignment. Nor did it hit the breakpoint, obviously.

I removed the 4th line, and it then work fine. I added it back in, it broke. I tried getting a different type from the Brendan.IC.Typed assembly. It worked fine. I replaced the WriteLine() statement with another ReadKey(true) statement. It broke.

using Brendan.IC.Typed;
using static System.Console;
ReadKey(true);
Type bigType = typeof(TypedEvolutionLookup<int>);
ReadKey(true);

A screenshot of the error for the latter case.

I got rid of the generic parameter. There was no change:

A screenshot of the error.

What worries me is that I think the error is happening, not with the execution of the typeof statement, but in the compiler for the IL! The error is being thrown between when I compile it, and when the top-level statements are executed! There is only one thing I can think of that would fit those constraints, and depend on the existence of a typeof line, and that it the IL runtime compiler itself!!! Yet the type is being found easily by the C#-to-IL compiler!

And the error is not happening with any of the other types in the assembly! Unfortunately, the TypedEvolutionLookup<> struct is the only generic type in the Brendan.IC.Typed assembly. However, it is not the only readonly struct. I have, though, tested some of the other readonly structs, and they do not have the same problem. The IL compiler seems to, for some reason, single out this one specific type, and, dependent or not on generics, this should not be happening.

I have, multiple times, restarted my computer, in case there is some secret RAM type-cache that I am not aware of. I have, multiple times, cleaned and rebuilt the solution, in case there is something weird with that. I have, multiple times, deleted the output directories of all my projects, in case some past versions are interfering with the present ones.

(All my class libraries compile to the same output directory; however, the console application compiles to its own, so as to avoid confusion.)

There has been no change. I do not understand this. I want to get the System.Type for this struct. Why has the IL compiler singled out this specific one? It has no funky attributes, except for the occasional [MaybeNullWhen(false)] in the parameters of its methods.

Why could this be happening, and how might I avoid it?