dimanche 5 mars 2023

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.





mardi 28 février 2023

How do I remove elements from multiple Lists that are properties of a generic object using reflection?

I have a generic object that could have mulitple Lists as properties.

How do I remove elements from those lists generically using reflection?

Let's say I have objects that are like below

public class ObjectA
{
    public List<long> listA
    public List<string> listB
}

public class ObjectB
{
    public List<int> listC
    public List<decimal> listD
}

How would I go about adding and removing elements from those lists generically?

Here's what I thought of, but it's wrong:

private bool PropertyIsGenericList(PropertyInfo property)
        {
            return property.PropertyType.IsGenericType && typeof(IList).IsAssignableFrom(property.PropertyType);
        }

private void RemoveElementsFromPropertyThatAreLists(object dto)
        {
            foreach (PropertyInfo property in dto.GetType().GetProperties())
            {
                if (dto != null && property != null && PropertyIsGenericList(property))
                {
                    RemoveElementsFromList(property, globalIndex); // Don't know what to pass to this
                }

            }
        }

protected void RemoveElementsFromList<ListType>(List<ListType>? columns, int? startingIndex = null)
        {
            startingIndex = startingIndex != null ? startingIndex.Value : globalIndex;
            if (columns != null)
            {
                for (int columnIndex = columns.Count - 1; startingIndex <= columnIndex; columnIndex--)
                {
                    columns.RemoveAt(columnIndex);
                }
            }
        }




lundi 27 février 2023

How do I get 'T from seq<'T> from a PropertyInfo array

I'm using reflection to try and create a datatable based on a record type. This works fine for a simple record type, but some of my records have sub records (also fine, just made the function recursive), or lists of sub records which is where I have my problem.

As an example, if i have the following types-

type ExampleSubType =
    {   PropertyA: string
        PropertyB: int }

type ExampleType =
    {   ID: int
        Name: string
        Example1: ExampleSubType list }

I'd like to create a data table with the following columns/types in this order-

ID: int
Name: string
PropertyA: string
PropertyB: int

I can already do this if I don't have a seq/arr/list anywhere in the types, but the ExampleSubType list part is throwing me off.

Here's the code I've got so far-


    let rec private createDataTableColumns record (propertyArr: PropertyInfo []) (dataTable: DataTable)  =
        propertyArr
        |> Seq.iteri(fun i property -> 
            let propType = property.GetType()
            let propValue = propertyArr.[i].GetValue(record)

            match FSharpType.IsRecord(propType), propValue with 
            | true, _ ->
                let subRecordType = propValue.GetType()
                let subPropertyArr = FSharpType.GetRecordFields (subRecordType)
                createDataTableColumns propValue subPropertyArr dataTable

            | false, :? seq<'T> as (_,test) -> 
                let subRecordType = test.GetType()
                let subPropertyArr = FSharpType.GetRecordFields (subRecordType)
                createDataTableColumns propValue subPropertyArr dataTable

            | _, _ ->
                dataTable.Columns.Add(property.Name, property.PropertyType) |> ignore
            )

The second match case is the issue. I can get it to match on that correctly but I'd like subRecordType to be typeof<'T>.

As it currently is, test.GetType() will return seq<'T>, not 'T and I don't know how to extract it from there.

I've also tried let subRecordType = typeof<'T>, which works elsewhere in my code, but here it will just return System.Object, not whatever type 'T is and i'm not sure why.





Using KProperty with List of objects

We're using Spring Data MongoDB with Kotlin. Kotlin comes with some nice typesafe Criteria Extensions (org.springframework.data.mongodb.core.query.TypedCriteriaExtensions).

given:

data class Foo(
  val id: String, 
  val oneBar: Bar, 
  val bars: List<Bar>)

data class Bar(val thingy: String)

You can use it to build Criteria in a typesafe manner, such as:

criterion = criterion + (Foo::id isEqualTo "id")

If you have a nested object Bar, you can use

criterion = criterion + (Foo::oneBar / Bar::thingy isEqualTo "thingy")

How do you use KProperty when you have an object Foo with a list of Bars and you want to write a Criteria based on a field of Bar

What I want to do is to filter on a property of Bar.

This doesn't work, but I want to do something like this:

criterion = criterion + (Foo::bars / <thing with list> / Bar::thingy isEqualTo "thingy")




dimanche 26 février 2023

Generic command-line argument parser with template, need implementation suggestion

I want to implement a C++ command line generic argument parser (also for fun). Existing popular argument parsers lack some functionalities.

  • gflags: Does not support vector very well.
  • getopt: C based, this is for without type.

I want a generic argument parser that can process arbitrary types, something like this:

class YourArgument {
   vector<int> your_ints;
   string my_str;
   bool help;
};
YourArgument your_arg; 
Argparse(your_arg, argv, argc); // A template

This Argparse can process something like "./run --help --my_str string --your_ints 1 2 3 run.txt".

I find something like C++17 structure binding can enable such implementation. If we are able to add some getters for a class, then we can implement it as follows.

class YourArgument {
   vector<int> your_ints;
   string my_str;
   bool help;
   auto& get(integral_constant<int, 0>) { return your_ints; }
   auto& get(integral_constant<int, 1>) { return my_str; }
   auto& get(integral_constant<int, 2>) { return help; }
   const char* getstr(int i) {
       if (i == 0) return "your_ints";
       if (i == 1) return "my_str";
       if (i == 2) return "help";
   }
};

template <typename T>
void Argparse_impl(T& your_arg, const char **argv, int &argc, int &c) {
    // Common recursive implementation
    // Skipped here
    Argparse_impl<i+1>(your_arg, argv, argc, c);
}

template <typename T>
void Argparse(T& your_arg, const char **argv, int &argc) {
    int c = 0;
    while (c < argc) Argparse_impl<0>(your_arg, argv, argc, c);
}

The parser implementation itself is just a normal recursive tricks, which is not the part that I need suggestion. My question is that is there any way to generate the boilerplate with macro?

I have tried this implementation, the code roughly looks like this (not the exact code I used). However, it drastically lengthen my compile performance. I have lots of such classes to compile, and the structs are very long.

#define MY_MACRO(...)\
    auto& get_tuple() { return forward_as_tuple(__VA_ARGS_); }\
    template<unsigned i> auto& get() { return get<i>(get_tuple()); }\
    const char* getstr() { static string strs = string(##__VA_ARGS_).split(); return strs[i]; }\




samedi 25 février 2023

Google Guava getTopLevelClassesRecursive not finding classes when running, only during test

I am using OpenJDK 17 and Guava 31.1-Jre. I am also using Spring Boot.

I have the line:

ImmutableSet<ClassPath.ClassInfo> classSet = ClassPath.from(ClassLoader.getSystemClassLoader())
                    .getTopLevelClassesRecursive(config.getFunctionPackage());

Whenever i run "mvn test", it finds the appropriate classes. But when i run it using "java -jar ...", it does not find a any classes. And i verified that "config.getFunctionPackage()" returns the same value both times.

Is a different class loader being used, or is something else going on?

thank you.