lundi 7 février 2022

Java: Is there a way to have a method to get the calling method name?

To get the current method name we can use the following:

new Object(){}.getClass().getEnclosingMethod().getName();

which should be called from within the method body.

Is there a way to have a service method which will return the method name for each calling method?

For example:

private void method1(){

   String thisMethodName = getMethodName(); //will return "method1"

}

private void method2(){

   String thisMethodName = getMethodName(); //will return "method2"

}

private void getMethodName(/*Any params?*/){

   //Is there an implementation for that? (In the same class or in some service class)

}




dimanche 6 février 2022

How do I know the field is private in golang?

Running this program will cause it to panic when I try to get the value of a private field via reflection.

How do I know the field is private and skip it?

The Golang version is 1.16.13.





How to override a method on a reified type [duplicate]

I would like to override a method on a reified type, but preserve all other methods. What is the simplest way to do that? For example:

I have:

(deftype Adapter []
 some.namespace/SomeProtocol
 (type-name-get [this] (:Adapter))
 ...)
(def adapter-instance (Adapter.))

And I want to get:

(def modified-adapter-instance
 (some-magic-fn adapter-instance type-name-get (fn [this] :ModifiedAdapter)))
(.type-name-get adapter-instance) => :Adapter
(.type-name-get modified-adapter-instance) => :ModifiedAdapter

The best solution that I've found is here. Is uses delegating-proxy macro to create a proxy from the object. Then you can use update-proxy to override methods.





samedi 5 février 2022

How to use std::chrono::duration in RTTR with Visual Studio >= 2019?

I am using RTTR for reflection and I'd like to use Chrono for certain types. However the following fails on >= Visual Studio 2019

  using microsecDouble = std::chrono::duration<double, std::micro>;
  auto microsecDoubleType = ::rttr::type::get<microsecDouble>();

with

  foo.cpp
c:\workspace\rttr\include\rttr/detail/type/type_data.h(331,1): error C2752: 'rttr::detail::template_type_trait<T>': more than one partial specialization matches the template argument list [c:\workspace\test\build\foo.vcxproj]
          with
          [
              T=non_ref_type
          ]
c:\workspace\rttr\include\rttr/detail/misc/template_type_trait_impl.h(135,1): message : could be 'rttr::detail::template_type_trait<T<Args...>>' [c:\workspace\test\build\foo.vcxproj]
c:\workspace\rttr\include\rttr/detail/misc/template_type_trait_impl.h(136,1): message : or       'rttr::detail::template_type_trait<T<Args...>>' [c:\workspace\test\build\foo.vcxproj]
c:\workspace\rttr\include\rttr/detail/misc/template_type_trait_impl.h(137,1): message : or       'rttr::detail::template_type_trait<T<Args...>>' [c:\workspace\test\build\foo.vcxproj]
c:\workspace\rttr\include\rttr/detail/misc/template_type_trait_impl.h(138,1): message : or       'rttr::detail::template_type_trait<T<Args...>>' [c:\workspace\test\build\foo.vcxproj]
c:\workspace\rttr\include\rttr/detail/type/type_impl.h(304): message : see reference to function template instantiation 'std::unique_ptr<rttr::detail::type_data,std::default_delete<rttr::detail::type_data>> rttr::detail::make_type_data<T>(void)' being compiled [c:\workspace\test\build\foo.vcxproj]
          with
          [
              T=non_ref_type
          ]
c:\workspace\rttr\include\rttr/detail/type/type_impl.h(371): message : see reference to function template instantiation 'rttr::type rttr::detail::create_or_get_type<non_ref_type>(void) noexcept' being compiled [c:\workspace\test\build\foo.vcxproj]
c:\workspace\rttr\include\rttr/detail/misc/template_type_trait_impl.h(44): message : see reference to function template instantiation 'rttr::type rttr::type::get<std::micro>(void) noexcept' being compiled [c:\workspace\test\build\foo.vcxproj]
c:\workspace\rttr\include\rttr/detail/misc/template_type_trait_impl.h(44): message : while compiling class template member function 'std::vector<rttr::type,std::allocator<rttr::type>> rttr::detail::template_type_trait<T>::get_template_arguments(void)' [c:\workspace\test\build\foo.vcxproj]
          with
          [
              T=non_ref_type
          ]
c:\workspace\rttr\include\rttr/detail/type/type_data.h(301): message : see reference to function template instantiation 'std::vector<rttr::type,std::allocator<rttr::type>> rttr::detail::template_type_trait<T>::get_template_arguments(void)' being compiled [c:\workspace\test\build\foo.vcxproj]
          with
          [
              T=non_ref_type
          ]
c:\workspace\rttr\include\rttr/detail/type/type_data.h(331): message : see reference to class template instantiation 'rttr::detail::template_type_trait<T>' being compiled [c:\workspace\test\build\foo.vcxproj]
          with
          [
              T=non_ref_type
          ]
c:\workspace\rttr\include\rttr/detail/type/type_impl.h(304): message : see reference to function template instantiation 'std::unique_ptr<rttr::detail::type_data,std::default_delete<rttr::detail::type_data>> rttr::detail::make_type_data<T>(void)' being compiled [c:\workspace\test\build\foo.vcxproj]
          with
          [
              T=non_ref_type
          ]
c:\workspace\rttr\include\rttr/detail/type/type_impl.h(371): message : see reference to function template instantiation 'rttr::type rttr::detail::create_or_get_type<non_ref_type>(void) noexcept' being compiled [c:\workspace\test\build\foo.vcxproj]
c:\workspace\test\foo.cpp(7): message : see reference to function template instantiation 'rttr::type rttr::type::get<microsecDouble>(void) noexcept' being compiled [c:\workspace\test\build\foo.vcxproj]

When compiling with VS 2017, or with Linux, everything is fine. Has anyone bumped into this or knows how to get around this?

Thanks,





Interact with multiple versions of an external jar file

JavaApplication1 wants to instantiate objects defined in the jar file of (fully trusted) JavaApplication2. Not normally a problem - add the external JavaApplication2 jar file to the build path of the JavaApplication1 project and then import the appropriate classes. Simples.

But imagine a scenario where JavaApplication1 needs to use multiple different historical versions of JavaApplication2 at the same time. e.g. Instantiate an instance of a JavaApplication2Object from version 1.5 of JavaApplication2.jar, and then, in the same thread, instantiate a separate instance of JavaApplication2Object from version 1.8 of JavaApplication2.jar.

In C#, I would use reflection to load and interact with the correct DLL. How does one do the same thing in Java in order to deal with the fact that the namespaces and class names are all identical across all versions of JavaApplication2?





Using Reflection to create an instance of logging service throws PlatformNotSupported Exception ... Activation attributes not supported error

I am trying to write a wrapper to abstract away logging frameworks. As part of the effort, I am trying to instantiate logging services from string names. When I try the below code to create an instance of one of the services it fails with the stated error. At the same time another service implementing the same interface and with a similar constructor works.

ILoggerService.cs

 public interface ILoggerService
 {
    void Log(string logLevel, string state, string eventId);
 }

NLogService

 public class NLogService : ILoggerService
    {
        private NLog.Logger _logger;
        private NLogNotifications _notifications;

        public NLogService(Func<LoggerConfiguration> notifiers)
        {
           _notifications = new NLogNotifications(notifiers);
            _logger = NLog.LogManager.GetCurrentClassLogger();
            
        }


        public void Log(string logLevel, string logMessage, string category)
        {
            _logger = NLog.LogManager.GetLogger(category);
            _logger.Log(GetLogLevel(logLevel), logMessage, category);
        }


        private NLog.LogLevel GetLogLevel(string levelName)
        {
            if (levelName == "Critical") levelName = "Fatal";
            return NLog.LogLevel.FromString(levelName);
        }
    }

Log4NetService

 public class Log4NetService : ILoggerService
    {
        private log4net.ILog _logger;
        private Log4NetNotifications _notifications;

        public Log4NetService(Func<LoggerConfiguration> config)
        {
            _logger = 
                log4net.LogManager.GetLogger(typeof(Log4NetService));
            BasicConfigurator.Configure();
            _notifications = new Log4NetNotifications(config);
        }
        void ILoggerService.Log(string logLevel, string logMessage, string category)
        {
            _logger = log4net.LogManager.GetLogger(category);
            _logger.Logger.Log(GetLogEvent(logLevel, logMessage, category));
        }

        private log4net.Core.LoggingEvent GetLogEvent(string logLevel, string logMessage, string category)
        {
            return new log4net.Core.LoggingEvent(new log4net.Core.LoggingEventData() { 
                Level = GetLogLevel(logLevel),
                Message = logMessage,
                LoggerName = category
            });
        }

        private Level GetLogLevel(string logLevel)
        {
            return _logger.Logger.Repository.LevelMap[logLevel];
        }
    }

The code that throws the exception looks like below -->


(_name, _getCurrentConfig, Logger) = (name, getCurrentConfig,
(ILoggerService?)Activator.CreateInstance(Type.GetType(lname)?.Assembly.FullName ?? "",
Type.GetType(lname)?.FullName ?? "", new [] { getCurrentConfig })?.Unwrap());
           




vendredi 4 février 2022

Can we use reflection to instantiate custom TypeScript model from a JSON string?

Is it possible to clone a JSON-generated object or string into a Typescript class which I created? We are building a model of our API using Typescript classes. There’s a base class which they all extend which has common/helper methods. When we do JSON.parse(response) to auto-generate objects it creates simple objects and not our custom objects.

Is there a way we can convert those JSON-generated objects into our custom objects, so long as the field names match up? And, to make things more robust, can this but done where our custom objects’ fields are other custom objects and/or arrays of them?

Here is our code, with comments of what we’d like to achieve.

base-model.ts

export class BaseModelObject {
    uuid: string; // All of our objects in our model and JSON have this required field populated
    matchUUIDs<T extends BaseModelObject>( obj: T): boolean {
        return obj.uuid == this.uuid;
    }
}

child-model.ts

import { BaseModelObject } from 'base-model';
export class Child extends BaseModelObject {
}

parent-model.ts

import { BaseModelObject } from 'base-model';
import { Child } from 'child-model';
export class Parent extends BaseModelObject {
  children: Child[];
}

JSON payload

{
    'uuid': '0632a35c-e7dd-40a8-b5f4-f571a8359c1a',
    'children': [
        {
            'uuid': 'd738c408-4ae9-430d-a64d-ba3f085175fc'
        },
        {
            'uuid': '44d56a0d-ad2d-4e85-b5d1-da4371fc0e5f'
        }
    ]
}

In our components and directives and such, we hope to use the helper function in BaseModelObject:

Component code

let parent: Parent = JSON.parse(response);
console.log(parent.uuid); // Works!  0632a35c-e7dd-40a8-b5f4-f571a8359c1a

// Want this to print ‘true’, but instead we get TypeError: parebt.matchUUID is not a function
console.log(parent.matchUUID(‘0632a35c-e7dd-40a8-b5f4-f571a8359c1a’));

// Want this to print ‘true’, but instead we get TypeError: parent.children[0].matchUUID is not a function
console.log(parent.children[0].matchUUID(‘d738c408-4ae9-430d-a64d-ba3f085175fc’));

The problem is that JSON.parse() is not creating our classes, it’s creating simple objects with key/value pairs. So we’re thinking of “cloning” the JSON-generated object into an instance of our class, like this:

base-model.ts

export class BaseModelObject {

    [key: string]: any;
    
    matchUUIDs<T extends BaseModelObject>( obj: T): boolean {
        return obj['uuid'] == this['uuid'];
    }

    cloneFields(obj: any) {
        for (let prop in obj) {
            this[prop] = obj[prop];
        }
    }
}

Component code

let parent: Parent = new Parent(); // Creates instance of our class
parent.cloneFields(JSON.parse(response)); // Copy JSON fields to our object
console.log(parent.matchUUID('0632a35c-e7dd-40a8-b5f4-f571a8359c1a')); // prints 'true'
console.log(parent.children[0].matchUUID('d738c408-4ae9-430d-a64d-ba3f085175fc')); // Still throws TypeError: parent.children[0].matchUUID is not a function

The problem now rests in the fact that the cloning of the Parent object did not recursively clone the JSON-generated Child objects into instances of our custom Child class.

Since our Parent object is typed at compile-time and it knows that the data type of the children array is Child[] (our custom class), is there a way to use reflection to instantiate the right class?

Our logic would need to say:

  1. Create an instance of our custom class
  2. Tell our instance to clone the fields from the JSON-generated object
  3. Iterate over the fields in the JSON-generated object
  4. For each field name from the JSON-generated object, find the "type definition" in our custom class
  5. If the type definition is not a primitive or native Typescript type, then instantiate a new instance of that "type" and then clone it's fields.

(and it would need to recursively traverse the whole JSON object structure to match up all other custom classes/objects we add to our model).

So something like:

cloneFields(obj: any) {
    for (let prop in obj) {
        let A: any = ...find the data type of prop...
        if(...A is a primitive type ...) {
            this[prop] = obj[prop];
        } else {
          // Yes, I know this code won't compile.
          // Just trying to illustrate how to instantiate
          let B: <T extends BaseModelUtil> = ...instantiate an instance of A...
          B.cloneFields(prop);
          A[prop] = B;
        }
    }
}

Is it possible to reflect a data type from a class variable definition and then instantiate it at runtime?

Or if I'm going down an ugly rabbit hole to which you know a different solution, I'd love to hear it. We simply want to build our custom objects from a JSON payload without needing to hand-code the same patterns over and over since we expect our model to grow into dozens of objects and hundreds of fields.

Thanks in advance! Michael