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.





GetProperty return Null for property that I see in debug

GetProperty method returns null, but I 100% sure that property I try to get exists, because I see it in debug.

I have List of dynamic rows that I get from CSV file. I need to get property value for specific row. To do that I use next code.

Type type = row.GetType();
PropertyInfo property = type.GetProperty("Site");
string propertyValue = property.GetValue(row);

But as result I receive "Object reference not set to an instance of an object." when GetValue runs. In debug I see this property and it's value for the row variable (screenshot attached). Also if I change code and try to get property directly everything works fine.

string propertyValue = row.Site;

Debug screenshot

But I can not use this approach because in the future I need to get property value by variable.

I am new in C# and .NET, please give an advice how to solve this problem.





vendredi 3 mars 2023

In java, can I compare child-of-child elements that share a class if their parent elements don't share a class or superclass?

I'm trying to map a response object from a rest call in our sprint java application. As this is on my work computer I'll simplify and rename the issue:

I get back a rest object containing plenty of already-mapped fields and a ShapeSelect object. The ShapeSelect object contains many kinds of specific shape objects that do not inherit from a common class, IE:

TriangleObject t;
SquareObject s;
PentagonObject p;

and so forth - in total about 25 such objects. Importantly, for each response object only one of these shape objects will be instantiated - the rest will be null.

Each of these specific shapes have a child element of the same class: BaseShape, which contains the fields and methods I need to map. Ex:

BaseShape base = response.getShapeSelect.getTriangleObject().getBaseShape();

So: I need to identify the ShapeSelect element that isn't null and grab the getBaseShape from that element 1) without using a long series of if statements and 2) in a way that our sonarQube scanner won't complain about.

My current plan is to use reflect to iterate across the fields of ShapeSelect until I find the non-null shape, then iterate over the methods looking for a method name that matches getBaseShape... I will report back on this, but I've been informed that it will probably run afoul of sonarQube. and I'm struggling to think of another way to accomplish this.