mercredi 2 décembre 2020

Get properties of properties

So, I am interested in getting all properties of a class via reflection ... and all properties of class-type properties (recursively).

I managed to get the first level of properties via reflections with a code like this:

foreach (var property in Target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
  var foobar = Factory.GetDealer(Target, property.Name);
}

and in the factory:

public static BaseDealer GetDealer(Object obj, string property) 
{
  var prop = obj.GetType().GetProperty(property);
  if (prop == null)
  {
    return null;
  }

  if (prop.PropertyType.IsPrimitive)
  {
    return GetPrimitivDealer(obj, property, Type.GetTypeCode(prop.PropertyType));
  }

  if (prop.PropertyType.IsClass)
  {
    return new CompositeDealer(obj, prop);
  }

  return null;
}

Obviously (in my mind that is), I'd then have something like this in the CompositeDealer:

   public CompositeDealer(Object obj, PropertyInfo propInfo)
   {      
      ComponentDealers = new List<BaseDealer>();
      Object compProp = propInfo.GetValue(obj);  // The new "origin" object for reflection, this does not work
      foreach (var property in compProp.GetType().GetProperties())
      {
        var dealer = Factory.GetDealer(compProp, property.Name);
        if (dealer != null)
        {
          ComponentDealer.Add(dealer);
        }
      }
   }

As noted in the comment, getting the new "base object" for reflection, that is to start the "second level" of reflection does not work, it returns null. I really struggle at this stage although I came so far and am pretty close (I think).

Help me StackOverflow, you're my only hope.





mardi 1 décembre 2020

C# How to call LINQ's First method with predicate using Reflection.Emit

im trying to wrap my head around Reflection.Emit, im playing around with it to understand how it works.

im trying to implement this method:

public static object GetTableKeyValue(object tableValue) => tableValue.GetType().GetProperties().First(property => property.GetCustomAttribute<KeyAttribute>() is not null).GetValue(tableValue);

This is what i did so far:

public static object GetTableKeyValueReflectionEmit(object val)
        {
            var getTableKeyValue = new DynamicMethod("GetTableKeyValueReflectionEmit", typeof(object), new Type[] { typeof(object) }, typeof(object).Module);
            getTableKeyValue.DefineParameter(1, ParameterAttributes.In, "tableValue");
            var il = getTableKeyValue.GetILGenerator(256);

            il.Emit(OpCodes.Ldarg_0);
            il.EmitCall(OpCodes.Call, typeof(object).GetMethod(nameof(object.GetType)), null);
            il.EmitCall(OpCodes.Call, typeof(Type).GetMethod(nameof(Type.GetProperties), new Type[] { }), null);
            Func<PropertyInfo, bool> predicate = property => (!property.GetCustomAttribute<KeyAttribute>().Equals(null));
            // im stuck here
            il.EmitCall(OpCodes.Call, typeof(Enumerable).GetMember(nameof(Enumerable.First)).OfType<MethodInfo>().First(method => method.GetParameters().Length == 1), new Type[] { typeof(Func<PropertyInfo, bool>) });
            il.EmitCall(OpCodes.Call, typeof(PropertyInfo).GetMethod(nameof(PropertyInfo.GetValue), new Type[] { typeof(object) }), new Type[] { typeof(object) });

            il.Emit(OpCodes.Ret);

            var getTableKeyValueDelegate = (GetTableKeyValueDelegate)getTableKeyValue.CreateDelegate(typeof(GetTableKeyValueDelegate));
            return getTableKeyValueDelegate(val);
        }

i cant understand how to define a predicate of type Func<PropertyInfo, bool> and pass it to the First method, and i cant really find good information on Reflection.Emit, i guess its not that common to do it.

Help would be appreciated.





Dealing with "convert to object" in a MemberExpression

I have a class that looks like this:

public class MyClass
{
  public int Id { get; set; }
  public string Name { get; set; }
}

I need to do this:

var memberExpressions = ConvertToMemberExpressions<MyClass>(o => o.Id, o => o.Name);

...

public static List<MemberExpression> ConvertToMemberExpressions<T>(params Expression<Func<T, object>>[] methodExpressions)
{
    var results = new List<MemberExpression>();
    foreach(var methodExpression in methodExpressions)
    {
        var memberExpression = methodExpression.Body as MemberExpression;
        results.Add(memberExpression);
    }
    return results;
}

The problem is that because of Func<T, object> (to be able to include both int and string as parameters) my methodExpression looks like this: {o => Convert(o.Id, Object)}, which is not what I need. I need to reach o.Id.

This does not happen with strings: {o => o.Name}, no conversion here.

I use Func<T,object> to be able to take advantage of Intellisense and reach the props of MyClass. I have tried using Func<T, dynamic> instead, but the result is the same.

It could be solved using multiple overloads:

public static ConvertToMemberExpressions<TClass, T1>(Expression<Func<TClass,T1>>[] methodExpression1)
public static ConvertToMemberExpressions<TClass, T1, T2>(Expression<Func<TClass,T1>>[] methodExpression1, Expression<Func<TClass,T2>>[] methodExpression2)
...

...but it is a sacrifice I would like to avoid if possible.


The question:

Is it possible to build o => o.Id from o => Convert(o.Id, Object) ?





What is the difference between java.lang.reflect and the maven org.reflections?

I am starting with reflections in java. Looking through an external project, I saw that the developer hast used the dependency org-reflections in his pom.xml instead of the already included java java.lang.reflect class. Does this maven dependency provide further methods?





How to get variable name from an object in Kotlin?

I have a function:

internal fun <T> List<T>.shouldBeNotEmpty(): ListAssert<T> = 
    Assertions.assertThat(this).withFailMessage("List should not be empty but is ${this::class.simpleName}!").isNotEmpty

and I am using it like:

val dataList: List<Data> = data.doSomething()

assertAll{
    ...
    dataList.shouldNotBeEmpty()
    ...
}

Now I have this message:

("List ${this::class.simpleName} should not be empty!")

but it (of course) showing in the terminal like this:

List ArrayList should not be empty!

but I would like to have it like:

List dataList should not be empty!

Can I somehow take the variable name out of an existing object using reflection or anything else?





Entity Framework Core - Generic Set method with reflection

I have this line of code:

dbContext.Set<????>().Add(this.arr);

I also have a Type variable. It it possible to put this type variabel in Set? If so, how can I achieve this?

Really hope someone can help me out with this one.





Generics and reflection in Java. Classes

I have a task where I have to implement method of creating object of the given class.

class Paper {}

class Bakery {}

class Cake extends Bakery {}

class ReflexiveBaker {
  
  /**
   * Create bakery of the provided class.
   * 
   * @param order class of bakery to create
   * @return bakery object
   */
  public Object bake(Class order) {
    // Add implementation here
  }
  
}

How should I implement this method correctly? I tried to do it in this way

public <T extends Bakery> T bake(Class<T> order) {
        try {
            return order.getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

But it always throws NoSuchMethodException. Moreover, from the task "It's guaranteed that all subclasses of Bakery will have public parameterless constructor." And InvocationTargetException is not imported in the task so it should be implemented without it. What's the problem?