Affichage des articles dont le libellé est Newest questions tagged reflection - Stack Overflow. Afficher tous les articles
Affichage des articles dont le libellé est Newest questions tagged reflection - Stack Overflow. Afficher tous les articles

vendredi 12 janvier 2024

How to resolve JAR conflicts with maven-shade-plugin

I have two projects: jartest and jarprj. jartest depends on poi 3.17, whereas jarprj depends on poi 5.10. jartest encounters an error when dynamically loading jarprj. The error message is as follows:

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.example.App.main(App.java:27)
Caused by: java.lang.NoSuchMethodError: org.apache.poi.xwpf.usermodel.XWPFDocument.getDocComments()Lorg/apache/poi/xwpf/usermodel/XWPFComments;
    at org.example.JarClass.test(JarClass.java:10)
    ... 5 more

The issue may stem from a conflict between the versions of poi. I attempted to rename poi using the maven-shade-plugin, but the error persists. The error message is as follows:

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.example.App.main(App.java:27)
Caused by: java.lang.NoSuchFieldError: Factory
    at shade.org.apache.poi.xwpf.usermodel.XWPFDocument.onDocumentCreate(XWPFDocument.java:304)
    at shade.org.apache.poi.xwpf.usermodel.XWPFDocument.<init>(XWPFDocument.java:149)
    at org.example.JarClass.test(JarClass.java:9)
    ... 5 more

jartest cannot upgrade its poi version, while jarprj requires poi 5.1.0. What methods are there to solve this? How can we resolve it using maven-shade-plugin?





mercredi 10 janvier 2024

lambdametafactory creation is quite slow compared to just using lambda

@Benchmark
public void testLambdaGeneration(Blackhole bh) {
    Function<Object, Object> function = a -> {
        if(a instanceof Alpha alpha) {
            return alpha.primitiveInt();
        }else {
            throw new RuntimeException();
        }
    };
    bh.consume(function);
}

@Benchmark
public void testManualGeneration(Blackhole bh) {
    try{
        MethodHandle mh = MethodHandles.lookup().findVirtual(Alpha.class, "primitiveInt", MethodType.methodType(int.class));
        MethodType type = mh.type();
        type = type.changeReturnType(Integer.class);
        CallSite callSite = LambdaMetafactory.metafactory(MethodHandles.lookup(),
                "apply",
                MethodType.methodType(Function.class),
                type.erase(), mh, type);
        Function<Object, Object> f = (Function<Object, Object>) callSite.getTarget().invokeExact();
        bh.consume(f);
    }catch (Throwable e) {
        throw new RuntimeException("Unreached");
    }
}

I want to use lambdametafactory to create constructor, getter and setter methods for reflection usage, and generated Function<> is just as fast as the direct call, which greatly satisfies my needs. However, when I use the above code to test the generation performance between lambdafactory and pure lambda, the result is quite unpromising:

LambdaTest.testLambdaGeneration  avgt   50      0.574 ±     0.015  ns/op
LambdaTest.testManualGeneration  avgt   50  29424.815 ± 20402.801  ns/op

I think the lambda function would use LambdaMetafactory internally, so the result should be consistent, but the actual result really shock me.

Is there any thing wrong with my code? How could I improve the LambdaMetafactory.metafactory()'s performance to match the pure lambda generation?





why always i have who add the time package on diverse progamming languages? [closed]

It's always strange to me to have to import the time package into the code, something that in my opinion is so important and basic that it's not directly included without being imported from.

Python sample:

import time time.sleep(1)


I see this in almost all programming languages. I want to understand why this happens, if it does, I'm trying to increase my general understanding of programming.

Ps: Thanks to everyone who wants to help by answering me!

I hope to learn a little more!





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?