vendredi 31 mars 2023

Roslyn: generate method optional parameters from reflected interface

Given SomeInterfaceType that has a method with optional parameters:

interface SomeInterface
{
    void SomeMethod(int a = 1, string c = "foo",
                    SomeType e = default, SomeType f = null);
}

SomeInterfaceType = typeof(SomeInterface);

How do I create a MethodDeclarationSyntax from the reflected type?

I'm retrieving the list of parameters from the MethodInfo like this:

private ParameterListSyntax GenerateParameterListSyntax(MethodInfo info)
{ 
    var parameters = info.GetParameters();
    var parameterList = new SeparatedSyntaxList<ParameterSyntax>();

    foreach (var parameter in parameters)
    {
        var parameterSyntax = SyntaxFactory.Parameter(SyntaxFactory.Identifier(parameter.Name))
                    .WithType(SyntaxFactory.ParseTypeName(TypeNameOrAlias(parameter.ParameterType)));

        if (parameter.IsOptional)
        {
            parameterSyntax = parameterSyntax.WithDefault( <<< WHAT DO I DO HERE?>>> );
        }

        parameterList.Add(parameterSyntax);
    }

    return SyntaxFactory.ParameterList(parameterList);
}

How do I autogenerate the EqualsValueClause to complete the WithDefault method ?

I leave here the output of RoslynQuoter for SomeInterface as reference.

CompilationUnit()
.WithMembers(
    SingletonList<MemberDeclarationSyntax>(
        InterfaceDeclaration("SomeInterface")
        .WithMembers(
            SingletonList<MemberDeclarationSyntax>(
                MethodDeclaration(
                    PredefinedType(
                        Token(SyntaxKind.VoidKeyword)),
                    Identifier("SomeMethod"))
                .WithParameterList(
                    ParameterList(
                        SeparatedList<ParameterSyntax>(
                            new SyntaxNodeOrToken[]{
                                Parameter(
                                    Identifier("a"))
                                .WithType(
                                    PredefinedType(
                                        Token(SyntaxKind.IntKeyword)))
                                .WithDefault(
                                    EqualsValueClause(
                                        LiteralExpression(
                                            SyntaxKind.NumericLiteralExpression,
                                            Literal(1)))),
                                Token(SyntaxKind.CommaToken),
                                Parameter(
                                    Identifier("c"))
                                .WithType(
                                    PredefinedType(
                                        Token(SyntaxKind.StringKeyword)))
                                .WithDefault(
                                    EqualsValueClause(
                                        LiteralExpression(
                                            SyntaxKind.StringLiteralExpression,
                                            Literal("foo")))),
                                Token(SyntaxKind.CommaToken),
                                Parameter(
                                    Identifier("e"))
                                .WithType(
                                    IdentifierName("SomeType"))
                                .WithDefault(
                                    EqualsValueClause(
                                        LiteralExpression(
                                            SyntaxKind.DefaultLiteralExpression,
                                            Token(SyntaxKind.DefaultKeyword)))),
                                Token(SyntaxKind.CommaToken),
                                Parameter(
                                    Identifier("f"))
                                .WithType(
                                    IdentifierName("SomeType"))
                                .WithDefault(
                                    EqualsValueClause(
                                        LiteralExpression(
                                            SyntaxKind.NullLiteralExpression)))})))
                .WithSemicolonToken(
                    Token(SyntaxKind.SemicolonToken))))))
.NormalizeWhitespace()




Is it technically possible for Intellij to statically know which exact class' method will be invoked on java.lang.Method m.invoke(instance) call

Let's say I have the following ReflectionTest.java file:

import java.lang.Class;
import java.lang.reflect.*;

public class ReflectionTest {
public static void main(String[] args) {
    try {

        // create an object of Dog
        Dog d1 = new Dog();

        // create an object of Class
        // using getClass()
        Class obj = d1.getClass();

        // using object of Class to
        // get all the declared methods of Dog
        Method[] methods = obj.getDeclaredMethods();

        // create an object of the Method class
        for (Method m : methods) {

            // get names of methods
            System.out.println("Method Name: " + m.getName());

            // get the access modifier of methods
            int modifier = m.getModifiers();
            System.out.println("Modifier: " + Modifier.toString(modifier));

            // get the return types of method
            System.out.println("Return Types: " + m.getReturnType());

            // invoke the method
            m.invoke(d1);
            System.out.println(" ");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

I am wondering, technically speaking, can a static analysis tool figure out, in 100% of the cases, which actual method of which specific class will be invoked by m.invoke(d1); and navigate me there? Kind of like the functionality IntelliJ already provides by holding the Cmd key and clicking with the left button of the mouse on a method - you get redirected to the actual method's implementation or get asked to choose one of all implementations in working with an interface, for example.

I am mostly interested in actual theoretical language level explanation as to what is possible and what not and why.





jeudi 30 mars 2023

How to return comma and pipe delimited strings containing the values of the properties of a C# object?

    var flags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | **strong text**System.Reflection.BindingFlags.FlattenHierarchy;
    System.Reflection.PropertyInfo[] infos = this.GetType().GetProperties(flags);



    StringBuilder sb = new StringBuilder();
   
    string typeName = this.GetType().Name;
    
    foreach (var info in infos)
    {
        object value = info.GetValue(this, null);

        sb.AppendFormat("{0}={1},{2}", info.Name, value != null ? value : "null",Environment.NewLine);
        
    }
    sb.Length -= 2;
    return sb.ToString().Substring(0, sb.Length - 1);
}

I have tried the above logic , but its returning like "name = john", "id= 23". But I need to display like "name","id" and then "john","23".





XUnit BeforeAfterTestAttribute how do I get runtime values of nameof parameters

This known pattern for BeforeAfterTestAttribute works as intended but i'm trying to do a bit extra on the after method. I'm trying to pass the value of a member which has just been "acted" in ProfileTests class, named json

//[WriteFileAfter("Company.json", nameof(json))]  //Not working
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class WriteFileAfter : BeforeAfterTestAttribute {
    public string FileName { get; }
    public string Json { get; }

    public WriteFileAfter(string fileName, string json) {
        FileName = fileName;
        Json = json;
    }

    //public override void Before(MethodInfo methodUnderTest) { //ignore
    //    Debug.WriteLine(methodUnderTest.Name); }

    public override void After(MethodInfo methodUnderTest) {
        Debug.WriteLine(methodUnderTest.Name);
        JsonUtils.WriteJsonToFile(**Json**, methodUnderTest.Name); 
                                   //^-- Json = 'json'
    }
}

The following code shows me using this attribute and passing "json" which is the nameof json, yes I understand it's just 'json'

public class ProfileTests
{ 
    public string json; 

    public ProfileTests()
    {
    }

    [Theory]
    [InlineData(@"test.txt")]
    [WriteFileAfter("Company.json", nameof(json))]
    public void MyTest(string fileName) {
        // Arrange
        // Act
        // Assert
 
        //Output?
        //json = JsonConvert.SerializeObject(package);
        json = "Hello World"
    }

}

How do I reflect back to the "value" of json so I can pass it to JsonUtils.WriteJsonToFile method because I know the name of the attribute I want the value. I've tried various reflection hacks (no expert) and can't seem to grasp how to do this. Thanks.

nameof(json) will return 'json' as expected but I wan the value I've google a bit but can't figure out the correct syntax.





mardi 28 mars 2023

Why is this JsonServerTest to access a domain via reflection isn't working?

We've implementing a class AutoRouterReflect that has the following method: public static Stream autorouterReflect(Object controller), where "controller" represents the DomainController we are receiving. We are filtering the methods with a specific annotation. We already implemented the Unit Tests but we also need the JsonServerTest, which we based on a StudentController already given. We addapted the code so it works, but it is exploding with the following error:

An established connection was aborted by software on the hosted computer java.net.SocketException: An established connection was aborted by software on the hosted computer at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:325) ... at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1589) at TestUtilsKt.put(TestUtils.kt:17) -> this.inputStream.bufferedReader().readText() at JsonServerTestForCinema$insert_film_in_cinema$1.invoke(JsonServerTestForCinema.kt:54) -> .put(""""{"id":"4","name":"Movie Name","room":"D","duration":"102","score":"4"}""")

I would aprecciate if anybody could help or give any ideias, we are getting crazy already.

We checked the amount of parameters that the domain constructor needs and it matchs, we also tried to change the amount of parameters and it says the wrong amount of parameters passed, so it knows the amount is correct but keeps not working and we can't justify or explain why, we already analize the code back and forth and we are only reaching dead ends.





java 17 - reflection to use methods in external jar files - Unable to make protected void java.net.URLClassLoader.addURL(java.net.URL) accessible

I've this code below which is used to load methods defined in some external jar files and in the web application using Spring Boot 2.7.10 version, it can invoke these external methods at run time.

This works fine with java 11, but when upgraded to java 17, it has error:

Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected void java.net.URLClassLoader.addURL(java.net.URL) accessible: module java.base does not "opens java.net" to unnamed module @221af3c0
    private static void addToClassPath(String jarFilePath) {
        try {
            File file = new File(jarFilePath);
            if (!(file.exists() && file.canRead())) {
                throw new UdfDirectoryNotAccessibleException(jarFilePath);
            }
            URL url = file.toURI().toURL();
            URLClassLoader urlClassLoader = (URLClassLoader) UdfInvoker.class.getClassLoader();
            Class urlClass = URLClassLoader.class;
            Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});

            // error here since java 17
            method.setAccessible(true);
            method.invoke(urlClassLoader, new Object[] { url });
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
            throw new UdfFailedLoadingException(jarFilePath, ex.getMessage(), ex);
        } catch (MalformedURLException ex) {
            throw new UdfJarFileNotAccessibleException(jarFilePath, ex.getMessage(), ex);
        }
    }

Does anyone know how this code can work with java 17 or if it can change to use something else which can work with both java 11 and java 17? Thanks.

NOTE:

  • Adding arguments to JDK is not an option as I cannot change that in servlet container Tomcat or JRE of development machine.
  • Downgrade java version to 11 is also not an option.




lundi 27 mars 2023

Get reflect.Value of nil pointer type

Using the Go reflect package I'd like to get a nil pointer of a particular type, for example I'd like a reflect.Value that represents *int with a value of nil not *0

I'm currently getting the zeroed value like this but this is *0 not nil

// varType is a reflect.Type
reflect.New(reflect.PtrTo(varType).Elem())

Will give me a zero value, e.g. *0 for *int

But what I can't quite workout is now to get a reflect.Value of say type *int and it be nil not *0

I understand why .Set(reflect.ValueOf(nil)) does not work. Perhaps I've missed a crucial step?





dimanche 26 mars 2023

ASP.NET MVC Nested Object Reflection for Hidden Values

I'm trying to figure out the best way to generate hidden values for nested objects to post on a form without any hardcoding. In other words, some partial view would just take in a model and generate hidden values for the lowest fields of the hierarchy.

Here's a basic example to illustrate what I'd like to do:

public class SomeModel {

    public ClassA firstClass { get; set; } = null!;

}
public class ClassA {
    
    public ClassB secondClass { get; set;} = null!;

}
public class ClassB {

    public ClassC thirdClass { get; set; } = null!;

}

public class ClassC {

    public string? someText { get; set;}

}

I would like to be able to generate the hidden value that represents the someText field within ClassC to model bind to the SomeModel class when the form is submitted, so it should look something like this:

<input type="hidden" name="firstClass.secondClass.thirdClass.someText" value="test" />

From what I can understand, some sort of reflection/recursion might be able to achieve this type of behavior without hardcoding. Ideally, the solution would be scalable to any number of nested objects and hidden values.

Thanks





MainActivity::class.java Unresolved reference: java?

I have problem in android studio with reflection after using Realm library. I'm using this implementation and the jar file is already added but still "java" is unresolved:

implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.10")
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'

and this :

buildscript {
ext.kotlin_version = "1.3.72"
repositories {
    google()
    jcenter()
    mavenCentral()
}
dependencies {
    classpath "com.android.tools.build:gradle:4.1.2"
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    classpath "io.realm:realm-gradle-plugin:10.11.1"


    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}

I tried all these solutions and no changes





samedi 25 mars 2023

ReflectionProbe.RenderProbe() not working on Android

In my project I have a curved reflective wall that is generated when the scene loads. During the generation, I create ReflectionProbes at intervals along the wall. I then call .RenderProbe() on each in turn and then wait for the job to complete on all of them before starting the scene (switching cameras on, allowing the player and NPC's to move etc.) This all works well in the editor but when I build for Android the call to RenderProbe() does exactly nothing. Calls to isFinishedRendering() never return true.

My guess is that I'm missing a setting somewhere but so far I haven't found it.

Any suggestions about where to look or things I should check are welcome.





Routing error in Laravel resulting in: Call to undefined method ReflectionUnionType::getName()

Currently, I am writing tests for my Laravel application. However, one test fails and I don't know why or how to solve it. I am running on Laravel 10 and PHP 8.2.3.

I have products and posts. Both models are morphed to the table and model comments because a user can write a comment under a product and under a post.

This is my route for the index function of the comments for either a product or a post with a given id:

Route::get('/comments/{commentableType}/{commentableId}', [CommentController::class, 'index'])->name('comments.index');

In the following, you will see my RouteServiceProvider. Here you can see, how I have binded the commentableType and commentableId. The strange thing now is, when I dd the line (new $model)->where('id', $id)->firstOrFail(); the correct product or post for the given idis being returned. Therefore, the route binding should be correct, I guess.

class RouteServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->routes(function () {
            Route::middleware('api')
                ->prefix('api/v1')
                ->namespace($this->namespace)
                ->domain(config('app.domain'))
                ->group(base_path('routes/api/comment.php'));
        });

        // Defines a pattern for categoryType
        Route::pattern('categoryType', 'product|post');

        // Returns the id of the product or post
        Route::bind('commentableId', function ($id) {
            $type = app()->request->route('commentableType');
            $models = ['product' => Product::class, 'post' => Post::class];
            $model = $models[$type];
            return (new $model)->where('id', $id)->firstOrFail();
        });
    }
}

This is my CommentController@index function:

public function index(IndexCommentRequest $request, String $commentableType, Product | Post $commentableModel): JsonResponse
{
    $comments = $request->perform($commentableType, $commentableModel);

    return $this->successWithPayload(new CommentResource($comments));
}

And this is my IndexCommentRequest file

class IndexCommentRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'sorting' => [
                'required',
                'string',
                'in:popular,discussed,newest',
            ],
        ];
    }

    public function perform(String $commentableType, Product | Post $commentableModel): LengthAwarePaginator
    {
        return $commentableModel->comments($this->input('sorting'))
            ->with('children')
            ->paginate(10);
    }
}

I have absolutely no idea why the following error is being thrown. I have already tried to google it but found no solution... I am so confused that the correct model is being found and therefore also returned but then the following error is being thrown:

array:5 [ // tests/Feature/Http/CommentController/IndexCommentTest.php:30
  "message" => "Call to undefined method ReflectionUnionType::getName()"
  "exception" => "Error"
  "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Support/Reflector.php"
  "line" => 151
  "trace" => array:62 [
    0 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/RouteSignatureParameters.php"
      "line" => 31
      "function" => "isParameterBackedEnumWithStringBackingType"
      "class" => "Illuminate\Support\Reflector"
      "type" => "::"
    ]
    1 => array:3 [
      "function" => "Illuminate\Routing\{closure}"
      "class" => "Illuminate\Routing\RouteSignatureParameters"
      "type" => "::"
    ]
    2 => array:3 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/RouteSignatureParameters.php"
      "line" => 31
      "function" => "array_filter"
    ]
    3 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/Route.php"
      "line" => 533
      "function" => "fromAction"
      "class" => "Illuminate\Routing\RouteSignatureParameters"
      "type" => "::"
    ]
    4 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/ImplicitRouteBinding.php"
      "line" => 80
      "function" => "signatureParameters"
      "class" => "Illuminate\Routing\Route"
      "type" => "->"
    ]
    5 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/ImplicitRouteBinding.php"
      "line" => 28
      "function" => "resolveBackedEnumsForRoute"
      "class" => "Illuminate\Routing\ImplicitRouteBinding"
      "type" => "::"
    ]
    6 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/Router.php"
      "line" => 947
      "function" => "resolveForRoute"
      "class" => "Illuminate\Routing\ImplicitRouteBinding"
      "type" => "::"
    ]
    7 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php"
      "line" => 41
      "function" => "substituteImplicitBindings"
      "class" => "Illuminate\Routing\Router"
      "type" => "->"
    ]
    8 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 180
      "function" => "handle"
      "class" => "Illuminate\Routing\Middleware\SubstituteBindings"
      "type" => "->"
    ]
    9 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php"
      "line" => 126
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    10 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php"
      "line" => 92
      "function" => "handleRequest"
      "class" => "Illuminate\Routing\Middleware\ThrottleRequests"
      "type" => "->"
    ]
    11 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php"
      "line" => 54
      "function" => "handleRequestUsingNamedLimiter"
      "class" => "Illuminate\Routing\Middleware\ThrottleRequests"
      "type" => "->"
    ]
    12 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 180
      "function" => "handle"
      "class" => "Illuminate\Routing\Middleware\ThrottleRequests"
      "type" => "->"
    ]
    13 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/app/Http/Middleware/JsonResponse.php"
      "line" => 20
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    14 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 180
      "function" => "handle"
      "class" => "App\Http\Middleware\JsonResponse"
      "type" => "->"
    ]
    15 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 116
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    16 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/Router.php"
      "line" => 797
      "function" => "then"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    17 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/Router.php"
      "line" => 776
      "function" => "runRouteWithinStack"
      "class" => "Illuminate\Routing\Router"
      "type" => "->"
    ]
    18 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/Router.php"
      "line" => 740
      "function" => "runRoute"
      "class" => "Illuminate\Routing\Router"
      "type" => "->"
    ]
    19 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Routing/Router.php"
      "line" => 729
      "function" => "dispatchToRoute"
      "class" => "Illuminate\Routing\Router"
      "type" => "->"
    ]
    20 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php"
      "line" => 200
      "function" => "dispatch"
      "class" => "Illuminate\Routing\Router"
      "type" => "->"
    ]
    21 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 141
      "function" => "Illuminate\Foundation\Http\{closure}"
      "class" => "Illuminate\Foundation\Http\Kernel"
      "type" => "->"
    ]
    22 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php"
      "line" => 21
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    23 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php"
      "line" => 31
      "function" => "handle"
      "class" => "Illuminate\Foundation\Http\Middleware\TransformsRequest"
      "type" => "->"
    ]
    24 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 180
      "function" => "handle"
      "class" => "Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull"
      "type" => "->"
    ]
    25 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php"
      "line" => 21
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    26 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php"
      "line" => 40
      "function" => "handle"
      "class" => "Illuminate\Foundation\Http\Middleware\TransformsRequest"
      "type" => "->"
    ]
    27 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 180
      "function" => "handle"
      "class" => "Illuminate\Foundation\Http\Middleware\TrimStrings"
      "type" => "->"
    ]
    28 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php"
      "line" => 27
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    29 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 180
      "function" => "handle"
      "class" => "Illuminate\Foundation\Http\Middleware\ValidatePostSize"
      "type" => "->"
    ]
    30 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php"
      "line" => 86
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    31 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 180
      "function" => "handle"
      "class" => "Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance"
      "type" => "->"
    ]
    32 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php"
      "line" => 62
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    33 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 180
      "function" => "handle"
      "class" => "Illuminate\Http\Middleware\HandleCors"
      "type" => "->"
    ]
    34 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php"
      "line" => 39
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    35 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 180
      "function" => "handle"
      "class" => "Illuminate\Http\Middleware\TrustProxies"
      "type" => "->"
    ]
    36 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 116
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    37 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php"
      "line" => 175
      "function" => "then"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    38 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php"
      "line" => 144
      "function" => "sendRequestThroughRouter"
      "class" => "Illuminate\Foundation\Http\Kernel"
      "type" => "->"
    ]
    39 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php"
      "line" => 563
      "function" => "handle"
      "class" => "Illuminate\Foundation\Http\Kernel"
      "type" => "->"
    ]
    40 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php"
      "line" => 324
      "function" => "call"
      "class" => "Illuminate\Foundation\Testing\TestCase"
      "type" => "->"
    ]
    41 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/tests/Feature/Http/CommentController/IndexCommentTest.php"
      "line" => 24
      "function" => "get"
      "class" => "Illuminate\Foundation\Testing\TestCase"
      "type" => "->"
    ]
    42 => array:3 [
      "function" => "Tests\Feature\Http\CommentController\{closure}"
      "class" => "P\Tests\Feature\Http\CommentController\IndexCommentTest"
      "type" => "->"
    ]
    43 => array:3 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/pestphp/pest/src/Factories/TestCaseFactory.php"
      "line" => 151
      "function" => "call_user_func"
    ]
    44 => array:3 [
      "function" => "Pest\Factories\{closure}"
      "class" => "P\Tests\Feature\Http\CommentController\IndexCommentTest"
      "type" => "->"
    ]
    45 => array:3 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/pestphp/pest/src/Concerns/Testable.php"
      "line" => 301
      "function" => "call_user_func_array"
    ]
    46 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/pestphp/pest/src/Support/ExceptionTrace.php"
      "line" => 29
      "function" => "Pest\Concerns\{closure}"
      "class" => "P\Tests\Feature\Http\CommentController\IndexCommentTest"
      "type" => "->"
    ]
    47 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/pestphp/pest/src/Concerns/Testable.php"
      "line" => 300
      "function" => "ensure"
      "class" => "Pest\Support\ExceptionTrace"
      "type" => "::"
    ]
    48 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/pestphp/pest/src/Concerns/Testable.php"
      "line" => 278
      "function" => "__callClosure"
      "class" => "P\Tests\Feature\Http\CommentController\IndexCommentTest"
      "type" => "->"
    ]
    49 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/phpunit/phpunit/src/Framework/TestCase.php"
      "line" => 1608
      "function" => "__test"
      "class" => "P\Tests\Feature\Http\CommentController\IndexCommentTest"
      "type" => "->"
    ]
    50 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php"
      "line" => 173
      "function" => "runTest"
      "class" => "PHPUnit\Framework\TestCase"
      "type" => "->"
    ]
    51 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/phpunit/phpunit/src/Framework/TestCase.php"
      "line" => 1214
      "function" => "runTest"
      "class" => "Illuminate\Foundation\Testing\TestCase"
      "type" => "->"
    ]
    52 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/phpunit/phpunit/src/Framework/TestResult.php"
      "line" => 728
      "function" => "runBare"
      "class" => "PHPUnit\Framework\TestCase"
      "type" => "->"
    ]
    53 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/phpunit/phpunit/src/Framework/TestCase.php"
      "line" => 964
      "function" => "run"
      "class" => "PHPUnit\Framework\TestResult"
      "type" => "->"
    ]
    54 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
      "line" => 684
      "function" => "run"
      "class" => "PHPUnit\Framework\TestCase"
      "type" => "->"
    ]
    55 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
      "line" => 684
      "function" => "run"
      "class" => "PHPUnit\Framework\TestSuite"
      "type" => "->"
    ]
    56 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/phpunit/phpunit/src/TextUI/TestRunner.php"
      "line" => 653
      "function" => "run"
      "class" => "PHPUnit\Framework\TestSuite"
      "type" => "->"
    ]
    57 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/phpunit/phpunit/src/TextUI/Command.php"
      "line" => 144
      "function" => "run"
      "class" => "PHPUnit\TextUI\TestRunner"
      "type" => "->"
    ]
    58 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/pestphp/pest/src/Console/Command.php"
      "line" => 119
      "function" => "run"
      "class" => "PHPUnit\TextUI\Command"
      "type" => "->"
    ]
    59 => array:5 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/pestphp/pest/bin/pest"
      "line" => 62
      "function" => "run"
      "class" => "Pest\Console\Command"
      "type" => "->"
    ]
    60 => array:3 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/pestphp/pest/bin/pest"
      "line" => 63
      "function" => "{closure}"
    ]
    61 => array:3 [
      "file" => "/Users/jt/Desktop/Bitbucket/Valet/dbb/vendor/bin/pest"
      "line" => 120
      "function" => "include"
    ]
  ]
]

This is my Pest test function but I get this error also without Pest or without PHPUnit when trying to make a normal API call to this route. Therefore, it has nothing to do with my testing code:

it('displays the first 10 comments for a given commentable model with children', function () {
    $product = Product::factory()->create();

    $comments = Comment::factory()->count(15)->create([
        'commentable_type' => Product::class,
        'commentable_id' => $product->id,
    ]);

    $comments->each(function ($comment) {
        Comment::factory()->count(2)->create([
            'parent_id' => $comment->id,
        ]);
    });

    $response = $this->get(route('comments.index', [
        'commentableType' => 'product',
        'commentableId' => $product->id,
        'sorting' => 'newest',
    ]));

    dd($response->json());
});

I am very thankful for every answer to help me solve this problem!





Best practice for displaying large number of fields in GUI

I have a class with about 300 fields - and firstly, no this cannot be changed as it is based on an external requirement.

I need to display these in a GUI, specifically a TableView.

Currently I am considering two approaches and am wondering which is most appropriate and/or are there any better solutions?

  • The first approach is using reflection to grab the field names and query values of instances of the class. The main benefit is if fields in the class change, this won't need to be updated. The main drawback is that reflection, especially showing field names to the user, seems bad practice to me.
  • The second approach is individually listing field names and fields, the main benefit and drawback being the opposites of reflection.

TIA





vendredi 24 mars 2023

How can application use reflection to use other dll's method which reply on the third dll

This is the definition of the DemoImport.dll, which relies on the RestSharp NuGet.

using RestSharp;

namespace DemoImport;

public class ImportClass
{
    public void JustAMethod()
    {
        Console.WriteLine("Hello");
        var client = new RestClient();
    }
}

This is the definition of the DemoClient, which use reflection to use the method "JustAMethod":

using System.Reflection;

Assembly assembly = Assembly.LoadFile(Directory.GetCurrentDirectory() + "\\Demo.dll");
Type? type = assembly.GetType("DemoImport.ImportClass");
object intance = Activator.CreateInstance(type)!;
type.GetMethod("JustAMethod").Invoke(intance,Array.Empty<object>());

However, I get error:

Unhandled exception. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.IO.FileNotFoundException: Could not load file or assembly 'RestSharp, Version=109.0.1.0, Culture=neutral, PublicKeyToken=598062e77f915f75'. System cannot find the target file。
File name: 'RestSharp, Version=109.0.1.0, Culture=neutral, PublicKeyToken=598062e77f915f75'
   at DemoImport.ImportClass.JustAMethod()
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Program.<Main>$(String[] args) in F:\Program.cs:line 6




Universal solution for changing structures using reflection

Suppose I have a structure with several nested structures:

type SomeInt int
type AnotherConfig struct {
    Value1 string
    Value2 int
    Value3 SomeInt
}
type SubConf struct {
    Value1 string
    Value2 int
    Conf   AnotherConfig
}
type Config struct {
    Value1 string
    Value2 int
    Conf   SubConf
}

I need an implementation of a function that will take as input a path from some final scalar field, and set there a value that will automatically be converted to the appropriate type:

func (conf *Config) ChangeValue(path string, value string) {
    //Need implementation
}

func main() {
    conf := Config{}
    // Usage example:
    conf.ChangeValue("Conf.Conf.Value3", "123")
}

Nested structures can constantly change during development, so a more or less universal solution is needed. Perhaps with support for a limited set of type conversions, such as support for only strings and ints, but they can be typed (as in the example).





jeudi 23 mars 2023

Call compile on an Expression that is known as object and I don't have the Types at compile time

I have a method

public static TDest SimpleStuff<TDest>(object obj) where TDest : new()
{
     var objType = obj.GetType();
     var destinationType = typeof(TDest);
     var method = typeof(SimpleMapper).GetMethod("CreateInit", BindingFlags.Static |    BindingFlags.Public, Type.EmptyTypes);
     var genericMethod = method.MakeGenericMethod(objType, destinationType);
     var expressionFuncAsObject = genericMethod.Invoke(typeof(SimpleMapper), null);
      
        ......
    }

expressionFuncAsObject is really Expression<Func<ObjType, TDest>>.

Is there a way the compiler will let me call .Compile on it? I can't cast it to (Expression<Func<ObjType, TDest>>) because the types are only known at runtime.

I tried using Expression.GetFuncType and passing that to Expression.Lambda

var funcType = Expression.GetFuncType(objType , destinationType);
var func = Expression.Lambda(funcType,
                Expression.Parameter(destinationType), Expression.Parameter(objType ) 
                ).Compile();

But I get System.InvalidOperationException: 'variable '' of type 'B' referenced from scope '', but it is not defined'.





C# Convert.ChangeType() int to enum

With the following model:

class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public WorkingLevel WorkingLevel { get; set; }
    // ...
}

enum WorkingLevel
{
    Unknown,
    Level1,
    Level2,
    Level3
}

and the following view model:

public class PatchResourceVM
{
    public List<PropertyValue> PropertyValues { get; set; } = new();
}

public class PropertyValue
{
    public string PropertyName { get; set; }
    public string? Value { get; set; }
}

I have an ASP.NET controller action like this which is supposed to updated properties of a person resource:

[HttpPatch("{id:int}")]
public async Task<IActionResult> UpdatePerson(int id, PatchResourceVM model)
{
    var person = await _dbContext.Employees.FindAsync(id);

    if (person is null)
    {
        return NotFound();
    }

    foreach (var propVal in model.ProrpertyValues)
    {
        var propertyInfo = person.GetType().GetProperty(propVal.PropertyName);
        if (propertyInfo is null)
        {
            return BadRequest($"Property {propVal.PropertyName} does not exist");
        }

        var oldValue = propertyInfo.GetValue(person, null);

        try
        {
            Type t = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
            object? safeValue = (propVal.Value == null) ? null : Convert.ChangeType(propVal.Value, t);
            propertyInfo.SetValue(person, safeValue, null);
        }
        catch (InvalidCastException)
        {
            return BadRequest($"{propVal.Value} is not a valid value for {propVal.PropertyName}");
        }
        // from this answer: https://stackoverflow.com/a/41466710/19363672

        var changeLog = new PersonChangeLog
        {
            PersonId = id,
            // ...
            PropertyName = propVal.PropertyName,
            OldValue = oldValue?.ToString(),
            NewValue = propVal.Value
        };

        _dbContext.Add(changeLog);
    }

    await _dbContext.SaveChangesAsync();
    return NoContent();
}

When I want to update an enum I get the InvalidCastException exception.

Payload:

{
  "propertyValues": [
    {
      "propertyName": "WorkingLevel",
      "value": "1"
    }
  ]
}

Response: "1 is not a valid value for WorkingLevel"

The code works fine for numeric and string types, but I cannot update the enum properties.

Is there any way to fix this?





mercredi 22 mars 2023

Context parameter (in context receivers functionality) not showing via reflection

Via reflection, I need to distinguish between a method with a context and a method without a context (Kotlin 1.8.0).

Let's say we have following dummy context and a class with two functions - one with the context, second without.

  class Context(val a: Int)

  class Foo {
    context (Context)
    fun bar() = a
    
    fun baz() = 1
  }

In runtime, we don't know which method is which, so let's try to distinguish them via reflection.

  val foo = Foo()

  val barMethod = foo::class.memberFunctions.first { it.name == "bar" }
  println("barMethod has ${barMethod.parameters.size} parameter(s)")

  val bazMethod = foo::class.memberFunctions.first { it.name == "baz" }
  println("bazMethod has ${bazMethod.parameters.size} parameter(s)")

The problem is, both return they have 1 parameter (and they are identical in all other public properties). But obviously, when called, bar will fail if provided only one parameter. If called as expected, it works.

  // println(barMethod.call(foo))        -- fails
  println(bazMethod.call(foo))

  with (Context(5)) {
    println(barMethod.call(foo))
  }
  println(barMethod.call(foo, Context(6))

When debugging, I found, there actually is an internal property descriptor on barMethod (KCallableImpl) which contains contextReceiverParameters property correctly showing 1 for barMethod and 0 for bazMethod. But it's not accessible.

Any idea, if there's any supported way of retrieving information about context receivers via reflection, or it simply hasn't been implemented yet?





C# (Unity): Automatically generate properties to access a field's fields

I created a small Presettable system: each Presettable object has a Preset field where Preset is simply a ScriptableObject:

public abstract class PresettableMonoBehaviour<TPreset>: MonoBehaviour, IPresettable<TPreset> 
        where TPreset : IPreset
    {
        [SerializeField] 
        private TPreset preset;
        public TPreset Preset => preset;

        ...
    }

Let's assume I defined this simple Presettable/Preset pair:

public class MyPresettable : PresettableMonoBehaviour<MyPreset>
{
        public int RelevantNumberIncremented() { return Preset.RelevantNumber + 1; }
}

public class MyPreset : Preset<MyPresettable>
{
        [field: SerializeField]
        public int RelevantNumber { get; private set; } = 10;
}

Ideally, I'd like to be able to access Preset.RelevantNumber by calling only RelevantNumber because logically it is directly part of MyPresettable. However I don't want to define properties to access each Preset's field one by one, I'd like to automatically generate (explicitly or implicitly) properties that fulfils the same role as private int RelevantNumber => Preset.RelevantNumber;

Is it possible?

I tried to look into custom Attributes, but the problem didn't change: I'd still have to call myAttribute.RelevantField.

Another option is to use strings and reflection, however I don't really like it because it requires you to know the exact name of every field in your Preset





lundi 20 mars 2023

How to remove reflections from the water surface?

I tried to convert to HSV space and define a range of values for the color of the reflection. Then I create the binary mask with the pixels within the range (Fig. 2), but this has a problem, since it segments also a part of the trees. How could I segment only the reflection of the water surface?. enter image description hereFig. 1. Original image with reflection

enter image description here

Fig. 2. Mask

Finally, I remove the reflections using the inpaint function, but this also has a problem as it does not restore correctly (Fig. 3). enter image description hereFig. 3. Without reflection

Here is the complete code:

import cv2
from PIL import Image, ImageEnhance

# Read image using OpenCV
img = cv2.imread("0336-CH.jpg")

# Convert image from RGB to HSV
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# Define range of values for the reflection color
umbral_bajo = (25, 0, 100) 
umbral_alto = (40, 50, 255) 

# Create binary mask with pixels within range
mask = cv2.inRange(img_hsv, umbral_bajo, umbral_alto)

# Removing reflections using the inpaint function
img_noreflect = cv2.inpaint(img, mask, 20, cv2.INPAINT_TELEA)

# Converting the OpenCV image to PIL
img_pil = Image.fromarray(img_noreflect)

# Create an object to control contrast with PIL
contrast = ImageEnhance.Contrast(img_pil)

# Applying a contrast factor of 1.5 to the image with PIL
img_pil_contrast = contrast.enhance(1.5)

# Create an object to control saturation with PIL
color = ImageEnhance.Color(img_pil_contrast)

# Applying a saturation factor of 1.2 to the image with PIL
img_pil_saturation = color.enhance(1.2)

# Converting the PIL image to OpenCV
img_opencv = np.array(img_pil_saturation)




Getting value of Value Types in an class using reflection in C#

I wrote the following snippet to illustrate a scenario I faced and can't come up with the answer to the observed behavior:

public class X
{

    public string XS { get; set; }
    public int XN { get; set; }
    public MyEnum Enum { get; set; }
}

void testValueTypesReflectionComparison()
{
    var x1 = new X { XN = 1, XS = "argh", Enum = MyEnum.Component };
    var x2 = new X { XN = 1, XS = "argh", Enum = MyEnum.Component };

    var xTypeProperties = x1.GetType().GetProperties();
    foreach(var property in xTypeProperties)
    {
        var x1PropertyValue = property.GetValue(x1, null);
        var x2PropertyValue = property.GetValue(x2, null);

        if (x1PropertyValue != x2PropertyValue)
        {
            Console.WriteLine($"different values on property: [{property.Name}]: x1: [{x1PropertyValue}] x2: [{x2PropertyValue}]");
        }
    }
}

Output:

enter image description here

I could not spot anything in the docs that mention particularities in getting value types.
Why are reflected properties XN and Enum values different in x1 and x2 ?





dimanche 19 mars 2023

TypeError: Cannot set properties of undefined (setting 'name') in Javascript, when the variable should have a value

I am in the midst of creating a recursive function for Get Object.getOwnPropertyDescriptors() from Javascript recursively, and flatten it .

This is the code:

let master = [];
function something (obj,str) {
    
    if (Object(obj)===obj) {
        pobj = Object.getOwnPropertyDescriptors(obj)
        for (let kk in pobj) {
            maststr = str;
        //console.log(obj);
        //console.log("line 8");
        //console.log(kk);
        if (master.includes(kk)||kk==="constructor"||kk==="globalThis"||kk==="global") { //circular reference // ||typeof obj[kk]==="function"
            return;
        } else {
            maststr = str + "." + kk ;
            console.log("line - 1st");
            console.log(maststr);
            console.log(kk);
            console.log(pobj[kk]);
            pobj[kk]["name"] = maststr;
            master.push(pobj[kk]);
            console.log("line - 2nd");
            console.log(maststr);
            if (maststr==="globalThis.Function.prototype.arguments"||maststr==="globalThis.Function.prototype.caller"
                ||maststr==="globalThis.Function.prototype.callee") continue;
            something(obj[kk], maststr);
        }
        
        }
    } else {
        //master.push(obj);
        return;
    }


    }


something(globalThis,"globalThis");
console.log(master);

It worked well until I reached the Object.assign property, which strangely became undefined, and threw the following error:

/Users/user/Documents/playground/playgroundtests_js/E16_2.js:19
            pobj[kk]["name"] = maststr;
                             ^

TypeError: Cannot set properties of undefined (setting 'name')
    at something (/Users/user/Documents/playground/playgroundtests_js/E16_2.js:19:21)
    at something (/Users/user/Documents/playground/playgroundtests_js/E16_2.js:25:4)
    at Object.<anonymous> (/Users/user/Documents/playground/playgroundtests_js/E16_2.js:38:1)
    at Module._compile (node:internal/modules/cjs/loader:1191:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1245:10)
    at Module.load (node:internal/modules/cjs/loader:1069:32)
    at Function.Module._load (node:internal/modules/cjs/loader:904:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:22:47

Indeed, when I console.log this property just before the error was thrown, it was undefined. But when I tested Object.getOwnPropertyDescriptors(Object.assign) on the node REPL, this returned an object.

Why is this so, and how do I solve this?





How to get chain of types of a variable using reflection?

I have types like this:

type A struct{}
type B A
type C B

than I have a variable:

var my C

How do I get all the reflect.Type for (my, C, B, A, ...) during runtime.

Of course the "chan" of types during runtime might be defferent. Im looking for general solution to this problem.





samedi 18 mars 2023

Type negation in Scala 3

Is it possible to implement fail proof Not[A] type in Scala 3? Here is a question asked some years ago: how-can-i-have-a-negation-type-in-scala. Unfortunately, a solution based on 'not given A <:< B' fails if either is an abstract type: absence of evidence is not an evidence of absence fallacy. Technically, with macros, it should be possible to verify the type of the expression and produce an error if full type information is not known. However, I'd like it also to work not just when 'not A <:< B', but only if A with B is effectively Nothing: either type is sealed/final and not possible to mix into the other. On the other hand, in that scenario, full information about both types shouldn't be required: if A is final, any upper bound on B which is neither a type variable nor A should work.

Motivation:

sealed trait Marker
sealed trait A[X]
final class Special[X <: Marker] extends A[X]
final class Generic[X :Not[Marker]#Proof] extends A[X]

In the example above, If I have an a :A[Marker], then I know for sure that a.asInstanceOf[Special[Marker]] is sound.





How to use detect virtual threads on java 19

Lets say I want to ship a program that runs on java 17 as that is what is available widely, but use reflection to detect if im running on a vm with the ability to produce a thread factory via Thread.ofVirtual().name("abc").factory(). Java prohibits reflective access to its internals when they are not properly configured with modules. How do I configure my program to be able to access this method reflectively? The reason for reflective access is to continue compiling into <jdk19 bytecode, but use reflection to use jdk19 features if they are present. Is there a combination of arguments or module-info.java contents that can achieve this goal, or is this not possible?

when you try this in jshell, here is what you get:

jshell --enable-preview
|  Welcome to JShell -- Version 19.0.2
|  For an introduction type: /help intro

jshell> Thread.class.getMethod("ofVirtual")
   ...>                 .invoke(null)
   ...>                 .getClass()
   ...>                 .getMethod("name", String.class, Long.TYPE)
   ...>                 .setAccessible(true)
|  Exception java.lang.reflect.InaccessibleObjectException: Unable to make public java.lang.Thread$Builder$OfVirtual java.lang.ThreadBuilders$VirtualThreadBuilder.name(java.lang.String,long) accessible: module java.base does not "opens java.lang" to unnamed module @30dae81
|        at AccessibleObject.throwInaccessibleObjectException (AccessibleObject.java:387)
|        at AccessibleObject.checkCanSetAccessible (AccessibleObject.java:363)
|        at AccessibleObject.checkCanSetAccessible (AccessibleObject.java:311)
|        at Method.checkCanSetAccessible (Method.java:201)
|        at Method.setAccessible (Method.java:195)
|        at (#1:5)

Exception java.lang.reflect.InaccessibleObjectException: Unable to make public java.lang.Thread$Builder$OfVirtual java.lang.ThreadBuilders$VirtualThreadBuilder.name(java.lang.String,long) accessible: module java.base does not "opens java.lang" to unnamed module @30dae81

adding required java.base; into the module-info.java does not seem to change the outcome either:

// src/main/java/module-info.java
module test_20230518_ {
    requires java.base;
}
// src/main/java/a/A.java

package a;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.ThreadFactory;

public class A {
    public static void main(String[] args) {
        ThreadFactory threadFactory = tf();
        threadFactory.newThread(() ->
                System.out.println("hi from " +
                        Thread.currentThread().getName()));
    }

    private static ThreadFactory tf() {
        Method[] methods = Thread.class.getMethods();
        boolean haveVirtual = Arrays.stream(methods)
                .anyMatch(m -> m.getName().equals("ofVirtual") &&
                        m.getParameterCount() == 0);

        if (haveVirtual) {
            try {
                Object b = Thread.class.getMethod("ofVirtual")
                        .invoke(null);
                b = b.getClass().getMethod("name", String.class, Long.TYPE)
                        .invoke(b, "prefix-", (long) 1);
                b = b.getClass().getMethod("factory")
                        .invoke(b);
                return (ThreadFactory) b;
            } catch (Throwable t) {
                throw new RuntimeException(t);
            }
        } else {
            return Thread::new;
        }
    }
}

still produces:

Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalAccessException: class a.A cannot access a member of class java.lang.ThreadBuilders$VirtualThreadBuilder (in module java.base) with modifiers "public volatile"
    at a.A.tf(A.java:31)
    at a.A.main(A.java:9)
Caused by: java.lang.IllegalAccessException: class a.A cannot access a member of class java.lang.ThreadBuilders$VirtualThreadBuilder (in module java.base) with modifiers "public volatile"
    at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:420)
    at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:709)
    at java.base/java.lang.reflect.Method.invoke(Method.java:569)
    at a.A.tf(A.java:26)
    ... 1 more

class a.A cannot access a member of class java.lang.ThreadBuilders$VirtualThreadBuilder (in module java.base) with modifiers "public volatile"





vendredi 17 mars 2023

Getting the classtype of a generic in an interface [duplicate]

I am trying to develop an http-library, mainly for getting a clue about how they work.

I am currently trying to automatically implement interfaces in which the methods look like this:

public Response<ExampleObject> getInformationAsExampleObject();

The interface is implemented and an InvocationHandler is created for each method.

Here is the problem: I haven't found a straightforward way to get the Class<?> for the T of the generic. In the example above it would be ExampleObject.class

It would be pretty simple if I was given an initialized object, but instead I am dealing with an unimplemented interface.

I have resorted to this:

Class.forName(Arrays.stream(((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()).toList().get(0).getTypeName());

and it feels like there has to be a more straightforward way to achieve the same result. The question is how.





jeudi 16 mars 2023

.NET 6 Is it possible to scan the background services and invoke AddHostedService

I am now using .NET 6 Worker Service to develop an backend service, and I have multi background services need to be registered by AddHostedService<> like:

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddHostedService<WorkerA>();
        services.AddHostedService<WorkerB>();
        services.AddHostedService<WorkerC>();
    })
    .Build();

await host.RunAsync();

I want to find a better way to register background services dynamically, for example:

var workers = Assembly.GetExecutingAssembly().GetTypes()
    .Where(worker =>
        worker is {IsClass: true, IsAbstract: false} &&
        !string.IsNullOrWhiteSpace(worker.Namespace) &&
        worker.Namespace.Equals(typeof(BaseWorker).Namespace))
    .ToArray();

foreach (var worker in workers)
{
    // Incorrect here
    services.AddHostedService<worker>();
}

However I failed since the worker is a Type not a class name. Could someone give me some instructions, thank you.





mercredi 15 mars 2023

In Java, how does one cast Class references (if possible)?

Let me setup the problem:

I am working with an API, lots of inheritance going on. It is very useful to pass around and work with Class type objects (e.g. String.class instead of an instance of String). It is also useful to range check the Class objects when working with them, so a method might have a parameter like this:

public void doSomething(Class<? extends GreatGrandParentClass> typeObject)
{ ... }

The problem is that the GreatGrandParentClass has A LOT of children, grandchildren, and great-grandchildren. So there are times when the type object passed as a parameter, or in a Collection, or whatnot, is a descendant of GreatGrandParentClass, but I'd like to cast the typeObject to it's actual type after confirming it's of that type. E.g.:

public void doSomething(Class<? extends GreatGrandParentClass> typeObject)
{
    Class thisType;
    if (FavoriteCousin.class.isAssignableFrom(typeObject))
        thisType = (FavoriteCousin) typeObject;
    ...
}

And then I use thisType as a parameter to a method that wants a Class object of FavoriteCousin type:

public void needsCousin(Class<? extends FavoriteCousin> cousinType)
{ ... }

But if I try to cast like I do above, I get:

Incompatible types: Class<CAP#1> cannot be converted to FavoriteCousin where CAP#1 is a fresh-type variable:
CAP#1 extends GreatGrandParentClass from capture of ? extends GreatGrandParentClass

Now, I rather expected that the way I did the cast was not correct, but I'm wondering if there is a correct to do that kind of cast, if possible?





Weird behaviour in custom generic class and reflection in Java

I have this custom generic class

@Component("box")
public class Box<T> {
    private T t; // T stands for "Type"

    public void set(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }

    @Override
    public String toString() {
        return "Box{" +
                "t=" + t +
                '}';
    }
}

In service class I have this method :

@Component("compo")
public class TempService {

    public Box<String> boxMeth(Box<String> stringBox)
    {
        System.out.println(Objects.nonNull(stringBox));
        System.out.println("Inside boxMeth!!!!!!");
        //System.out.println(stringBox.get());
        return stringBox;
    }

}

Inside main I have the following code using reflection :

TempService tmp =(TempService)apcon.getBean("compo");
        tmp.testMethod("1");
Box<Integer> box=(Box)apcon.getBean("box");
        box.set(10);
        Class classObj = tmp.getClass();
        Object obj = classObj.getDeclaredConstructor().newInstance();
        Method postHookMethod = obj.getClass().getMethod("boxMeth",Box.class);
        postHookMethod.invoke(obj,box); // getting allowed because of forceful action by reflection

        //tmp.testMethod(new Box<Integer>()); // not allowed

Now I know as bosMeth method allows Box of type String and by this line tmp.testMethod(new Box<Integer>()) I am trying to pass an Integer type compiler is throwing error.

But when I am setting value by reflection complier is allowing it. More interesting if I keep this line commented //System.out.println(stringBox.get()); compiler is not throwing any error.

So my questions are:

  1. How can Box <String> box can hold an object of type Box <Integer> when I am trying to pass the argument by reflection?

  2. If the value can be held then why there is an exception from this line //System.out.println(stringBox.get()); ? //class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')





NullPointerException inside a method called via the reflection API

I'm getting a NullPointerException when I try to access a static property via reflection.

This is a simplified version of my class:

package test;

@Component
public class CallMe {
  private static Foo foo;

  // Autowired constructor to "inject" the static field
  @Autowired
  public CallMe(Foo autowiredFoo) {
    CallMe.foo = autowiredFoo;
  }

  public static Thing doSomething() {
    return CallMe.foo.bar();
  }
}

And this is the code calling the method:

Class<?> clazz = Class.forName("test.CallMe");
Method method = clazz.getMethod("doSomething", (Class<?>[]) new Class[0]);
Thing theThing = (Thing) method.invoke(null, new Object[0]);

The NullPointerException happens because CallMe.foo is null when I call doSomething via the reflection API. However, my log reads something like this:

Constructor begins
- autowiredFoo is NOT null
- foo is NOT null
Constructor ends
doSomething begins
- foo is null !!!
- NullPointerException

It's not a race condition, I can delay the call to the static method as long as I want.

Why does this happen? Is the reflection API creating a different "copy" of the class, instead of using the one already loaded? Or am I missing something?

And more importantly, how can I solve it? The obvious answer would be "don't declare your method as static if it really isn't static, duh...", but sadly that's not an option. The calling method is in a third-party library and they made it a requeriment that doSomething must be static.





mardi 14 mars 2023

Convert csv row to java object

I'm writing a program that requires using a CSV as the database (I'm well aware this is questionable choice but at the moment I have no other option) and I'm trying to figure out a way to generalize the implementation. So far I have implemented indexing successfully but this requires passing the entire row as a string and parsing it in the constructor of the "entity" which is not ideal and is error prone.

I have managed to implement a processor that extracts all the fields that have getters:

public class EntityProcessor {
    private boolean isGetter(Method method) {
        return Modifier.isPublic(Modifier.methodModifiers()) &&
                method.getName().matches("^get[A-Z].*") &&
                !method.getReturnType().equals(void.class) &&
                method.getParameterCount() == 0;
    }

    private List<Method> findGetters(Class<?> c) {
        return Arrays.stream(c.getDeclaredMethods()).filter(this::isGetter).toList();
    }

    public List<Field> getFieldsWithGetters(Class<?> c) {
        var getters = new HashSet<>(findGetters(c).stream().map(Method::getName).map(String::toLowerCase).toList());
        return Arrays.stream(c.getDeclaredFields())
                .filter(field -> getters.contains("get" + field.getName().toLowerCase())).toList();
    }
}

and lets assume I have an entity class similar to (uses lombok library to generate getters):

@Getter
public class TestClass {
    private Long a;
    private Integer b;
    private String c;
    private String d;
}

now lets say I have parsed a line of the CSV which was 0,1,c,d. based on the fields in my entity I know that 0 is Long, 1 is Integer and c and d are string. How can I actually use this type to parse the value? .valueOf() does not exist in the field.getType() and I'm not sure how I can invoke it to parse the value. I essentially want something like this:

class Main {
    public static void main(String[] args) {
        var processor = new EntityProcessor();
        var values = List.of("0", "1", "2", "3");
        var fields = processor.getFieldsWithGetters(TestClass.class);
        for (var i=0; i<values.size();i++){
            fields.get(i).getType().valueOf(values.get(i));
        }
    }
}

P.S: I'm aware that the order of the fields is not guaranteed and I'll be using a bit more logic to parse the fields in the correct order, but for this example lets just assume the values are in the correct order of the fields.





Not able to re-assign value to final member using Reflection API

I am trying to change the final member value using reflection API but it is not working.Below is the sample code.

public class Fun {
    private static final String AA = "something";
    public static void getValue() {
        if(AA != null)
            System.out.println("I m here");
    }

}


public class Test {

    @org.testng.annotations.Test
    public void fun() throws ReflectiveOperationException {
        setFinalStaticField(Fun.class, "AA", null);
        Fun.getValue();
    }

    private static void setFinalStaticField(Class<?> clazz, String fieldName, Object value)
            throws ReflectiveOperationException {

        Field field = clazz.getDeclaredField(fieldName);
        field.setAccessible(true);

        Field modifiers = Field.class.getDeclaredField("modifiers");
        modifiers.setAccessible(true);
        modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);

        field.set(null, value);
    }
}

The above code is always printing "I m here" ,however I changed the value of the variable to null. Can anyone please help me on that, why this is not working as expected.





Identify DU level when partially applied

Suppose we have a DU with 3x levels parameterised by reference types as shown:

type DU =
    | X of Object
    | Y of Object
    | Z of Object

Noting that the GetUnionCases function within the FSharp.Reflection.FSharpType namespace can, when provided with the type information for a DU, return a UnionCaseInfo array.

I am looking for a function f: ('T -> DU) -> UnionCaseInfo, such that:

  • f X = UnionCaseInfo for level X.
  • f Y = UnionCaseInfo for level Y.
  • ...and so on.

Assuming a many-to-1 mapping between level and type parameter as shown at the start... Is this even possible?

If the DU levels were parameterless, the GetProperties() member provided by typeof<DU> contains singleton instances that can, via PropertyInfo.Name, be tied back to a corresponding UnionCaseInfo.

Alternatively... If the parameter type was different across all levels, we could do something akin to:

let x = X

Subsequently calling x.GetType().GetMethods() shows a MethodInfo for Invoke(<some type>); using <some type> we could tie it back to the underlying level.

Unfortunately, neither of these methods (as far as I am aware) are suitable for this particular example!





lundi 13 mars 2023

C++ Variadic Template: Construct a list of class members

I would like to create class members through a variadic template so that a template defined like this:

template<typename firstType, firstName, Rest... rest>
class MyClass{
FirstType firstName;
//do something recursvy: https://stackoverflow.com/questions/7230621/how-can-i-iterate-over-a-packed-variadic-template-argument-list
};

with the following instance:

class MyClass<int A, float B, char c>

would generate a class like this:

class MyClass{
int A;
float B;
charc;
}

How do I do this?

I can only picture doing this with nasty C macros.





Preserve argument information for inspect when stacking decorators

I'm writing a decorator that should pass a query to the function based on one of its parameters.

This is how it currently looks like, but not finished yet (still experimenting):

def pass_query(service: str, query: str):
    def decorate(decoratee):
        @functools.wraps(decoratee)
        def decorator(*args, **kwargs):
            params = inspect.getfullargspec(decoratee)
            if "query" in params and service == params.get("service", None):
                kwargs["query"] = query
            return decoratee(*args, **kwargs)

        return decorator

    return decorate

The problem is that inspect.getfullargspec(decoratee) doesn't retrieve any useful information with two or more decorators as then the other ones loose the information about the function parameters.

@pass_query("foo", "q1.sql")
@pass_query("bar", "q2.sql")
def track_report(service: str, query: Optional[str] = None) -> None:
    pass

Is there a way to preserve the parameters so that the decorators won't break reflection as if there was only one decorator?





Invoke generic extension method via reflection results in error is not a GenericMethodDefinition

I have the below extension method which I am trying to invoke with various instantiated classes in an array. As extension methods cannot be invoked with dynamic I have tried using the array type as object or IMessage. However, as this calls MassTransit and Azure Service Bus, they need the exact type for it to work, even though it will compile. I have thought that perhaps reflection would work however the below results in System.InvalidOperationException: System.Threading.Tasks.Task``1[Helix.Sdk.Contracts.CommandResponse] ExecuteCommand[Object](MassTransit.IBus, System.Object, System.Threading.CancellationToken) is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true.

Is there anyway for this to work so it knows the correct type at runtime?

foreach (var command in commands)
{
   //Bus.ExecuteCommand(command); //won't work with dynamic or object at runtime

   var func = new Func<IBus,object, CancellationToken, Task<CommandResponse>>(BusCommandExtensions.ExecuteCommand);
   func.Method.MakeGenericMethod(command.GetType());
   await func.Invoke(Bus,command, CancellationToken.None);
}

public static class BusCommandExtensions {

    //Removed other methods for brevity     

    public static async Task<CommandResponse> ExecuteCommand<T>(this IBus bus, T command, CancellationToken cancellationToken = default) where T : class =>
        await ExecuteCommand(
            bus, command, _ => { },
            cancellationToken
        );

}




dimanche 12 mars 2023

Python : cannot call static method on run-time retrieved type

I have a base class:

class MyBaseClass:
    @abstractmethod
    def from_list(list_float: List[float]) -> Self:
        pass

    @staticmethod
    @abstractmethod
    def fn() -> int: 
        pass

All children of that class implement from_list and static fn, since they are abstract.

Now, I have another class 'MyOptions' :

class MyOptions:
    @abstractclass
    def related_to_type(): type(MyBaseClass)

All MyOptions children implement related_to_type, which returns a type that is a child of MyBaseClass. What I want is:

Provided a MyOptions child (which is unknown until runtime), call fn on its related type, returned by related_to_type(). In other term, I want:

options: MyOptions = MyOptionChild()
type_opt = options.related_to_type() # this should return a MyBaseClass child type 
result = type_opt.fn() # error here 

The error is that type_opt contains an variable of type <class 'abc.ABCMeta'>, on which I cannot call my static function fn. PS : I cannot make MyOptions generic with a type argument because the related type is known at run-time only

What can I do to call a static function on a variable containing a "reflected class" in Python ? Typically, in java, you would do:

Method method = myBaseClassChild.getMethod("fn");
int result = method.invoke(null);




Get static method with generic using reflection

I have several extension methods with same name and different receiving argument:

public static List<T>? MapTo<T>(this List<ClassA_DataModel> data) where T : ClassA_BusinessModel, new() { ... }
public static List<T>? MapTo<T>(this List<ClassB_DataModel> data) where T : ClassB_BusinessModel, new() { ... }
... (+50)

and need to use reflection to invoke the right method according to the List<MyClassX_DataModel> passed as parameter:

var businessObjects = (typeof(MapperModel)?.GetMethod(nameof(MapperModel.MapTo))?.MakeGenericMethod(businessModelType).Invoke(null, new[] { dataObjects }) as IList)?.Cast<object>().ToList();

The problem is that I get an Exception because there are more than one method with the same name:

System.Reflection.AmbiguousMatchException: 'Ambiguous match found'

My guess would be to do something like this:

var myMethod = typeof(MapperModel)?.GetMethods().FirstOrDefault(m => m.Name == nameof(MapperModel.MapTo) && m.XXXX == businessModelType);
var businessObjects = (myMethod.MakeGenericMethod(businessModelType).Invoke(null, new[] { dataObjects }) as IList)?.Cast<object>().ToList();

but I don't know how to get the comparision part to work, provided that I have to match a List<BussinessModel>. Any suggestion? Thanks in advance!





vendredi 10 mars 2023

How to use class loader to hack the Singleton Pattern (create multiple instances of Singleton with different classloaders)

I read this :Breaking of sinlgleton by two different class loaders But I can't create more than one instance of a Singleton with more than one class loader. Can some one help me provide an example of how you can break the Singleton pattern with multiple class loaders please?

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
    
    public static  void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {

        ClassLoader cl1 = new CustomClassLoader();
        ClassLoader cl2 = new CustomClassLoader();
        Class<?> singClass1 = cl1.loadClass(SingletonObject.class.getName());
        Class<?> singClass2 = cl2.loadClass(SingletonObject.class.getName());
        
        Method getInstance1 = singClass1.getDeclaredMethod("getSingletonObject");
        Method getInstance2 = singClass2.getDeclaredMethod("getSingletonObject");
        Object singleton1 = getInstance1.invoke(null);
        Object singleton2 = getInstance2.invoke(null);

        System.out.println("ok");
        
    }
}
public class SingletonObject {
    private static SingletonObject ref;
    private SingletonObject () //private constructor
    { }

    public  static  SingletonObject getSingletonObject()
    {
        if (ref == null){
            ref = new SingletonObject();
            System.out.println("create new");
        }else{
            System.out.println("already have it");
        }
        return ref;
    }


    public Object clone() throws CloneNotSupportedException
    {throw new CloneNotSupportedException ();
    }
}
public class CustomClassLoader extends ClassLoader{
}





Find all variables by their type [duplicate]

I have several values of type Upgradable in my C# script:

public class Player 
{
   public Upgradable speed;
   public Upgradable damage;
   public Upgradable reload;

   int someVar1; //etc., there are other variables
}

And I should create a method GetAllUpgrades() in each class to run trough upgrades and update each of them. Here I store an array of Upgradable values that I've added manually. But are there some ways to do it automatically?





Updating an object using efcore

I was creating a UpdateEntityCommand and I wanted to make it flex. If some properties are null then these properties are not modified and they will have the same value before. I've done it with using Reflection. However I am not that sure that this is wise way to do it. These are my entities and codes.

Drink

public class Drink : Product
{
    public string Name { get; set; }
    public int Id {get; set; }
    public double Price { get; set; }
    public string? Explanation { get; set; }
    public double? Calories { get; set; }
    public bool HasStock { get; set; } = true;
    public int? Volume { get; set; }
    public int DrinkCategoryId { get; set; }
    public virtual DrinkCategory DrinkCategory { get; set; }

}

UpdateDrinkDto

public class UpdateDrinkDto
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public double? Price { get; set; }
    public bool? HasStock { get; set; } = true;
    public string? Explanation { get; set; }
    public int? Volume { get; set; }
}

And the methods

public async Task<DrinkDto> Handle(UpdateDrinkCommand request, CancellationToken cancellationToken)
        {
            Drink ?drink = await _drinkRepository.GetAsync(x => x.Id == request.UpdateDrinkDto.Id, x => x.Include(x=>x.DrinkCategory).ThenInclude(x=>x.Menu));
            _drinkBusinessRules.DoesDrinkExists(drink);
            await _businessRules.IsOwnerResponsibleForRestaurant(request.OwnerId, drink.DrinkCategory.Menu.RestaurantId);

            SetProperties(request.UpdateDrinkDto, drink);

            Drink updatedDrink = await _drinkRepository.UpdateAsync(drink);

            DrinkDto response = _mapper.Map<DrinkDto>(updatedDrink);

            return response;





        }

        private void SetProperties(UpdateDrinkDto updateDrinkDto, Drink drink)
        {
            PropertyInfo[] properties = typeof(UpdateDrinkDto).GetProperties();
            foreach (PropertyInfo property in properties)
            {
                if (updateDrinkDto.GetType().GetProperty(property.Name).GetValue(updateDrinkDto) != null) typeof(Drink).GetProperty(property.Name).SetValue(drink, property.GetValue(updateDrinkDto));
            }
        }

It works as I want it. However I want to learn is there any other way to implement this look. Thank you





jeudi 9 mars 2023

GetConstructor class type return null

I am using System.Reflection.Emit and trying to create type in Runtime, and x.Attribute.GetConstructor(x.Types) return null value. This happens after I am changing Class Library from .net framework 4.8 to .net Standard 2.0 and installing System.Reflection.Emit v4.7.0 (tried with all possible verson) from NuGet

private static CustomAttributeBuilder CreateCustomAttribute(AttributeBuilder x)
    {
        if (x.Types == null)
        {
            x.Types = Type.EmptyTypes;
            x.Values = Array.Empty<object>();
        }

        var constructorInfo = x.Attribute.GetConstructor(x.Types);
        var displayNameAttributeBuilder = x.Properties == null ? new CustomAttributeBuilder(constructorInfo, x.Values) :
            new CustomAttributeBuilder(constructorInfo, x.Values,
                x.Properties
                    .Select(prop => x.Attribute
                        .GetProperty(prop)).ToArray(), x.PropertiesValues, 
                Array.Empty<FieldInfo>(),Array.Empty<object>());
        return displayNameAttributeBuilder;
    }

The Differnec to call the Methode is: *With working Reflection:

[ComVisible(true)]
    [__DynamicallyInvokable]
    public ConstructorInfo GetConstructor(Type[] types)
    {
      return this.GetConstructor(BindingFlags.Instance | BindingFlags.Public, (Binder) null, types, (ParameterModifier[]) null);
    }

*With Not working:

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
        public ConstructorInfo? GetConstructor(Type[] types) => GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, types, null);

So GetConstructor is not working anymore any idea what is the problem?





mercredi 8 mars 2023

Determine the function signature of an anonymous function in scala

Suppose that there is a function that returns an anonymous function:

 def impl(): Function1[Int, String] = new Function1[Int, String] {
    def apply(x: Int): String = "ab" + x.toString
  }


  impl: ()Int => String

Now, impl() will return an anonymous function. Suppose that I do not know the signature of function because the impl function is implemented elsewhere, and I'd like to ask whether we can convert it into a correct function instance:

impl().asInstanceOf[Function1[Int, String]]   // How to determine the function signature of the anonymous function, in this case Function1[Int, String]?

Since scala does not support generic function, I first consider getting the runtime type of the function:

import scala.reflect.runtime.universe.{TypeTag, typeTag}
def getTypeTag[T: TypeTag](obj: T) = typeTag[T]
val typeList = getTypeTag(impl()).tpe.typeArgs

It will return List(Int, String), but I fail to recognize the correct function template via reflection.





Exception when trying to cast a dynamically loaded type

I'm trying to load dll's at runtime and use types within them.

Unfortunately I'm running into some strange issues that I don't fully understand. Here's a minimal version of the code that demonstrates the problem:

public class Component
{
}

class Program
{
    static void Main()
    {
        Assembly assembly = Assembly.LoadFile(Assembly.GetExecutingAssembly().Location);
        var componentType = assembly.GetExportedTypes().FirstOrDefault(x => x.Name == "Component");

        Console.WriteLine(componentType == typeof(Component));

        ConstructorInfo constructor = componentType.GetConstructors()[0];
        var component = constructor.Invoke(new object[0]);

        var k = (Component)component;
    }
}

In the console, it prints 'False', and when I try to do the cast it crashes with:

System.InvalidCastException: 
[A]TypeTest.Component cannot be cast to [B]TypeTest.Component. 
Type A originates from 'TypeTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'C:\Users\Home\Documents\TypeTest\TypeTest\bin\Debug\net6.0\TypeTest.dll'. 
Type B originates from 'TypeTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'C:\Users\Home\Documents\TypeTest\TypeTest\bin\Debug\net6.0\TypeTest.dll'.

Ultimately I'm going to be using dependency injection across dynamically loaded dll's, which works, but doesn't obey the singleton scope as it's treating the types as different even though they are referring to the same class in the same codebase.





mardi 7 mars 2023

Using protobuf reflection to check for default values

When am iterating over a a protobuf message fields using reflection, I'd like to check if a sub-message or a map's value has a default value. I am currently checking for ByteSizeLong() == 0, which works, but according to the documentation is linear in the number of sub-fields, making it inefficient for large sub-messages.

I tried to use HasField() instead, but it isn't working.

Is there a problem in my code or can HasField() not be used for this? And if the latter is the case, is there an O(1) function that can be used?

Here's a minimal example:

The .proto file:

message Wrapper {
  string value = 1;
}

message M {
  map<int64, Wrapper> map = 1;
  optional Wrapper    msg = 2;
}

And the C++ code:

int main() {
    M msg;
    auto status = JsonStringToMessage(R"(
        {
          "map": {
            "1": { "value": "string1" },
            "2": {}
          },
          "msg": {}
        })",
        &msg);

    test(msg);
}

void test(const Message& msg) {
    const auto* descr = msg.GetDescriptor();
    const auto* refl = msg.GetReflection();
    for (int i = 0; i < descr->field_count(); ++i) {
        const auto* fd = descr->field(i);
        if (fd->is_map()) {
            for (const auto& element : refl->GetRepeatedFieldRef<Message>(msg, fd)) {
                const auto* descr = element.GetDescriptor();
                const auto* refl = element.GetReflection();
                const auto* fdValue = descr->map_value();
                std::cout << "Element size: " << refl->GetMessage(element, fdValue).ByteSizeLong()
                          << ", has field: " << refl->HasField(element, fdValue) << "\n";
            }
            continue;
        }

        if (fd->type() == FieldDescriptor::TYPE_MESSAGE && !fd->is_repeated()) {
            std::cout << "Message size: " << refl->GetMessage(msg, fd).ByteSizeLong()
                      << ", has field: " << refl->HasField(msg, fd) << "\n";
        }
    }
}

And finally, the results:

Element size: 9, has field: 1
Element size: 0, has field: 1
Message size: 0, has field: 1




lundi 6 mars 2023

boost::describe: Can I add annotations to types and/or members?

Is it possible, using the boost::describe library, to add additional information about a given type or member?

For instance, if I have a class described like this:

BOOST_DESCRIBE_STRUCT(Foo, (), (bar, baz))

Is there any way to add some kind of additional info, like a tag or flag, to either the members or the type? There's a lot of information about members, such as name, type, visibility, etc. Is there a way to add some custom info to that?

To flag types, I've tried using type traits with std::true_type or std::false type.

However, these are cumbersome to use, because template specializations must be done in the namespace where the type traits were defined, not the namespace where the types being described are defined.





C# reflection "Object does not match target type." when calling a method

I have the following code in a factory:

private readonly Type? ModelType;

public object Resolve()
    {
        if (ModelType != null)
        {
            var service = Activator.CreateInstance(ModelType);
            if (service != null)
            {
                var inf = service.GetType().GetInterfaces().FirstOrDefault();
                if (inf != null)
                {
                    MethodInfo? method = inf.GetMethod("LoadParameters");
                    if (method != null)
                    {
                        method.Invoke(inf, null);
                    }

                    return inf;
                }
            }
            throw new ArgumentOutOfRangeException($"Service must extend IBackendParamService<>!");
        }
        else
        {
            throw new ArgumentOutOfRangeException($"Type not found!");
        }
    }

Method invocation method.Invoke(inf, null); returns an exception with the message "Object does not match target type."

I don't understand why. The variable inf is the variable where I found the method. Any help would be appreciated!





How to create a new instance Serializable class by reflection in Kotlin?

Stub object for testing purposes fails to create via reflection:

internal fun <T : ParentThingy> KClass<in T>.random(): T {
    val createViaConstructor = constructors.first()
    val args = createViaConstructor.parameters.associateWith { param ->
        when (param.type) {
            Int::class.starProjectedType -> gen.primitive().int()
            // other options omitted for brevity
            else -> error("$param not supported, it's type ${param.type}")
        }
    }

    @Suppress("UNCHECKED_CAST")
    return createViaConstructor.callBy(args) as T
}

becase of:

parameter #2 serializationConstructorMarker of fun `<init>`(kotlin.Int, kotlinx.serialization.internal.SerializationConstructorMarker?): some.child.Thingy not supported, it's type kotlinx.serialization.internal.SerializationConstructorMarker?

-- the class has @Serializable annotation. Reflection with a factory method works fine. Any ideas how to make reflection work with a primary constructor?





dimanche 5 mars 2023

How to get list of attributes value from solution in C# other than by reflection?

I have a large solution with multiple projects, but for simplicity let's shrink it down to three projects:

  1. Application.Client (it has a reference to Application.Common project)
  2. Application.Common
  3. Application.SourceGenerator

Application.Client

This project has interfaces with specific custom attribute to each method

public class ProcessActionAttribute : Attribute
{
    public ProcessActionAttribute(string guid)
    {
        Value = guid;
    }

    public string Value { get; }
}

Example:

public interface IProcessService
{
    [ProcessAction("2e145a71-dfeb-4c40-ae3f-d0ff5c45d7f6")]
    void ProcessItem();

    [ProcessAction("9795d060-962a-4790-bea0-9380a6ffd3eb")]
    void CreateItem();
}

Application.SourceGenerator

Generates a class ProcessActionGuidProvider in Application.Client with a static dictionary of all methods with their guids extracted from ProcessActionAttribute.

Application.Common

The idea of this class library is to be referenced and used by other libraries to get list of all ProcessActionAttribute guids of all interfaces methods in the solution.

Since Application.Client references Application.Common I cannot create circular reference by referencing Application.Client in Application.Common.

What do I want to achieve?

My goal is to use the class generated by source generator from Application.Client (and from more projects in the solution) in Application.Common.

Issues on the way

My initial idea was to implement in source generator that extracts guids from Application.Client but it also adds the ProcessActionGuidProvider class to the same project. Once I add another project to be analyzed, it would create yet another provider in another project.

Another idea that I had before that was to use reflection to do that and keep the dictionary in cache to increase performance. This worked nicely, but application slowed down and tests were going slow as hell.

Is there anything else other than reflection and source generator that I could use?

Possible fix 1

The easiest way to fix it would be to move all interfaces from Application.Client to Application.Common and use source generator to generate the class ProcessActionGuidProvider in Application.Common.

Unfortunately, for undisclosed reasons I cannot do that. I have to find a workaround for it.

Possible fix 2

I could also just create a static method that does the same job as SourceGenerator using reflection, but the performance is very slow due to how large this solution is.