I often find myself testing using typeOf whenever I'm lost. Is there a similar way to print all properties or fields of a variable, similar to Object.keys (JavaScript) or vars (Python)?
mardi 29 novembre 2022
lundi 28 novembre 2022
How can I cast an object to string and use it in a Linq query using Reflection
There's the problem I made an Extension method to IQueryable and I want to get property name and value to do a select on it the thing is that I am using Expression tree and try to search rows by the use of Contain() method which is needs a parameter of type string to do the job. my code is doing well while I do the search over string properties but I want this method to do the search on other types like int, decimal, datetime and even booleans so I need to get the property cast it to string and search for the matching values.
what I tried so far is:
private static readonly MethodInfo _tostring = typeof(Object).GetMethod("ToString") ?? throw new Exception("Cannot create Method");
public static IQueryable<T> Search<T>(this IQueryable<T> items, string propertyName, string filterValue)
{
MethodInfo _compare =
(((Expression<Func<string, bool>>)(s => s.Contains("aa"))).Body as MethodCallExpression ?? throw new Exception("Cannot Create Method"))
.Method;
var property = typeof(T).GetProperty(propertyName) ?? throw new Exception("Couldn't Get the property");
var row = Expression.Parameter(typeof(T), "row");
var prop = Expression.Property(row, property);
// now making sure if the type is string
if (property.PropertyType != typeof(string))
{
//Here I want to cast it to string but the problem is exactly here anything I try feels like a dead end
prop = Expression.Call(prop, _tostring);
}
var func =
Expression.Lambda<Func<T, bool>>
(
Expression.Call
(
prop,
_compare,
Expression.Constant(filterValue)
),
row
);
return items.Where(func);
}
How to access list property of derived type through reflection?
Consider this code sample:
public abstract class BaseClass {
public virtual void DoThing() {
...
}
}
public class DerivedClass {
public override void DoThing() {
...
}
}
public class SomeClass {
public List<DerivedClass> MyProp {get; set;}
}
...
// assume we have obj of SomeClass and prop as PropertyInfo of MyProp
var pt = prop.PropertyType;
if (pt.IsGeneric && (pt.GetGenericTypeDefinition() == typeof(List<>)) && (pt.GetGenericArguments()[0].IsSubclassOf(typeof(BaseClass))))
{
var val = pt.GetValue(obj); // here it is not null
var list = val as List<BaseClass>; // list is null
list?.ForEach(o => o.DoThing());
}
How can I get list of BaseClass
and call (probably) overridden method for each of them? As I try to cast property value to list it become null
.
dimanche 27 novembre 2022
Reflection - missing 1 parameter
I am using extention function from this post: https://stackoverflow.com/a/72111931/1305993
In my test I have:
@Before
fun setUp() {
savedStateHandle = SavedStateHandle()
savedStateHandle["areaId"] = 1L
saveImageUseCase = Mockito.mock(SaveImageUseCase::class.java)
repo = FakeRepository()
viewModel = AreaEditViewModel(repo, savedStateHandle, saveImageUseCase)
}
@Test
fun setUpArea() = runTest {
viewModel.callPrivateFunc("setUpArea", 2L)
}
In my viewModel I have:
private suspend fun setUpArea(areaId: Long) {
repository.getAreaById(areaId).first() {
savedStateHandle["area"] = it
true
}
}
When I run test I get: Callable expects 3 arguments, but 2 were provided. java.lang.IllegalArgumentException: Callable expects 3 arguments, but 2 were provided.
I cannot figure out what is that third parameter missing
How to convert string object to generic object at runtime?
Simplify example:
I Have a class with support of direct cast from string
public class MyClass {
public static explicit operator MyClass(string stringValue) => new MyClass();
public static MyClass Parse(string value) => new MyClass();
}
I can cast String to MyClass at compile time like (MyClass)"Some value". But when I cast from string to this class type at runtime, I have Invalid cast from 'System.String' to 'SomeNamespace.MyClass'.
How Can I solve this problem? I need to cast from string to generic class at runtime
About Usecase:
This is a parser for runtime text data models. At runtime I have a IList<string> from API that represent Object. I need to convert this IList to my domain Object at Runtime. I can't hardcode concrete class implementation (becouse I only know what object it is at runtime). Here is my implementation, of a generic function that should transform a dictionary of PropertyInfo (of generic object) and Strings (of values from API) to generic object. I think I need some DoDirectCast(Type type, string value) that will direct cast value to type to set parameters of y generic object
public T Transform<T>(Dictionary<PropertyInfo, string> arrOfPropOfT)
{
var returnObject = new T();
foreach (var keyValuePair in arrOfPropOfT)
{
Type propertyType = keyValuePair.value;
string castableValue = keyValuePair.key;
object? value = DoDirectCast(propertyType, castableValue);
propertyInfo.SetValue(returnObject, value)
}
return returnObject;
}
I have tried:
var result = Convert.ChangeType("Parsable_string_value", typeof(MyClass));
var converter = TypeDescriptor.GetConverter(typeof(MyClass));
var result = converter.CanConvertFrom(typeof("Parsable_string_value"));
But in both I have an error: Invalid cast from 'System.String' to 'SomeNamespace.MyClass'
So my problem is that String class have no idea how to convert itself to Unknown classes. But all my Unknown classes know how to cast to themselves from String... like (UnknownClass)("Some string value")
samedi 26 novembre 2022
Reflection - private method
In my test I have:
@Before
fun setUp() {
savedStateHandle = SavedStateHandle()
saveImageUseCase = Mockito.mock(SaveImageUseCase::class.java)
repo = FakeRepository()
viewModel = AreaEditViewModel(repo, savedStateHandle, saveImageUseCase)
}
@Test
fun setUpArea() = runTest {
val method = viewModel.javaClass.getDeclaredMethod("setUpArea", Long::class.java)
method.isAccessible = true
method.invoke(viewModel, 2L)
...
}
in my viewModel:
private suspend fun setUpArea(areaId: Long) {
repository.getAreaById(areaId).first() {
savedStateHandle["area"] = it
true
}
}
when I run my test I get: com.rachapps.area_feature.viewModel.AreaEditViewModel.setUpArea(long) java.lang.NoSuchMethodException: com.rachapps.area_feature.viewModel.AreaEditViewModel.setUpArea(long) at java.base/java.lang.Class.getDeclaredMethod(Class.java:2707) at com.rachapps.area_feature.viewModel.AreaEditViewModelTest$setUpArea$1.invokeSuspend(AreaEditViewModelTest.kt:61)
jeudi 24 novembre 2022
why the autowired bean is null while reflect execute private method and is not null while reflect execute public method?
controller
@Controller
@RequestMapping("/test")
@Slf4j
public class TestController {
@Autowired
private ReflectServiceImpl reflectService;
@PostMapping("/reflectTest")
@ResponseBody
public Object reflectTest(@RequestParam String name, @RequestParam String age){
try {
Method method = ReflectServiceImpl.class.getDeclaredMethod("reflectTest", String.class, String.class);
// method.setAccessible(true);
return method.invoke(reflectService, name, age);
}
catch (Exception e){
log.error("reflectTest出现错误{}", e.getMessage(), e);
}
return "error";
}
}
service
@Service
@Slf4j
public class ReflectServiceImpl extends AbstractReflectService {
@Autowired
private ReflectCallService reflectCallService;
public String reflectTest(String name, String age){
String s = name + "-" + age;
log.info("==> {} ==> ???", s);
return reflectCallService.getName();
}
@Override
public String getCombineData(String name, String age){
String s = name + "-" + age;
log.info("==> {}", s);
return reflectCallService.getName();
}
@Override
public String addressFrom() {
rainNow();
return reflectCallService.getName();
}
}
when ReflectServiceImpl#reflectTest()
is public and TestController
execute
Method method = ReflectServiceImpl.class.getDeclaredMethod("reflectTest", String.class, String.class);
return method.invoke(reflectService, name, age);
is run right. but when ReflectServiceImpl#reflectTest()
is private and TestController
execute
Method method = ReflectServiceImpl.class.getDeclaredMethod("reflectTest", String.class, String.class);
method.setAccessible(true);
return method.invoke(reflectService, name, age);
is throw exception
java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.yichen.casetest.controller.TestController.reflectTest(TestController.java:168)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException: null
at com.yichen.casetest.test.service.reflect.impl.ReflectServiceImpl.reflectTest(ReflectServiceImpl.java:24)
... 59 common frames omitted
other there I have a @Aspect to trigger cglib proxy like below proxy
there is the debug image private method public method
and my test demo is here https://github.com/yichen17/case-test core class => LogAspect、ReflectServiceImpl、TestController
I want to know why there two case have different result and the cause reason.
how to insert a class instance into RTTR sequential view without getting its wrapped value?
All
I am creating a generic binary serializer and got block on how to insert a class instance into a sequential view.
Here is the example code:
#include <iostream>
#include <rttr/type>
#include <rttr/registration.h>
using namespace rttr;
struct Item {
int i ;
};
struct MyTestClass {
std::vector<Item> seq;
};
RTTR_REGISTRATION
{
using namespace rttr;
registration::class_<MyTestClass>("TestClass")
.constructor<>()
.property("seq", &MyTestClass::seq);
registration::class_<Item>("Item")
.constructor<>()
.property("item", &Item::i);
}
void CreateInst(rttr::instance inst) {
auto localobj = inst.get_type().get_raw_type().is_wrapper() ? inst.get_wrapped_instance() : inst;
auto p = localobj.get_type().get_property("item");
p.set_value(inst, 100);
}
int main()
{
MyTestClass inst;
for (auto prop : rttr::type::get_by_name("TestClass").get_properties()) {
auto type = prop.get_type();
if (type.is_sequential_container()) {
auto val = prop.get_value(inst);
auto view =val.create_sequential_view();
view.set_size(1); //just for demo
rttr::variant var = view.get_value_type().create();
CreateInst(var);
//get its wrapped and insert 'it', it will have the correct result
//Item it=var.get_wrapped_value<Item>();
view.set_value(0, var);
prop.set_value(inst, val);
}
}
std::cout << inst.seq[0].i << std::endl;
}
it always output '0' instead of '100' on screen, unless I get its wrapped value and insert. But that is not what I want.
Could any expert help me to improve on this ?
Thank you.
BR Ray
mercredi 23 novembre 2022
Why am I getting a casting error in .NET 7 after using reflection?
Is reflection and casting different in .NET 7 vs .NET Framework? I'm porting a project and getting this casting error after moving the code over. The wierd thing is this class implements that interface. This code works in .NET 4.x.
foreach (Assembly pluginAssembly in pluginAssemblies)
{
try
{
// Look for class(s) with our interface and construct them
foreach (var type in pluginAssembly.GetTypes())
{
Type iDesigner = type.GetInterface(typeof(IFireworksDesigner).FullName);
if (iDesigner != null)
{
object instance = Activator.CreateInstance(type); // creates an object
IFireworksDesigner designer = (IFireworksDesigner)instance; // throws an exception
// do stuff
}
}
}
catch(Exception ex)
{
//Something really bad must have happened.
MessageBox.Show("Fatal error reflecting plugins in assembly '" + pluginAssembly.FullName + "'.\r\n" +
"The error message is:\r\n\r\n" + ex.Message);
}
}
mardi 22 novembre 2022
Java 17 reflection: assign the "this" reference of a lambda object
This code runs fine in java 11.
package test;
import org.junit.Assert;
import org.junit.Test;
import java.lang.reflect.Field;
import java.util.function.Consumer;
public class LambdaArg1ReflectionTest {
@Test
public void test() throws IllegalAccessException {
// Create a lambda with reference to parent class (this)
Consumer<String> lambda = s -> this.parseInt(s, 7);
// Get the value from the lambdas "this" reference
Field lambda_arg1_field = lambda.getClass().getDeclaredFields()[0];
lambda_arg1_field.setAccessible(true);
Object lambda_arg1_value = lambda_arg1_field.get(lambda);
// Assert that the value is as we expected
Assert.assertEquals(this, lambda_arg1_value);
// Attempt to assign the same value
lambda_arg1_field.set(lambda, lambda_arg1_value);
}
private int parseInt(String s, int i) {
return Integer.parseInt(s + i);
}
}
But, in java 17 it throws an exception:
java.lang.IllegalAccessException: Can not set final test.LambdaArg1ReflectionTest field test.LambdaArg1ReflectionTest$$Lambda$40/0x0000000800c191a8.arg$1 to test.LambdaArg1ReflectionTest
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:80)
at java.base/jdk.internal.reflect.UnsafeQualifiedObjectFieldAccessorImpl.set(UnsafeQualifiedObjectFieldAccessorImpl.java:79)
at java.base/java.lang.reflect.Field.set(Field.java:799)
at test.LambdaArg1ReflectionTest.test(LambdaArg1ReflectionTest.java:23)
- Why?
- Is it not supposed to work in java 17?
- Is there any way to work around this?
Obviously this is an example. What the real code attempts to do is to replace the lambdas this reference with a spy object, invoke the lambda and then capture the arguments given to this.parseInt. Ultimately what it does is to serialize the first method invocation of a lambda.
lundi 21 novembre 2022
Having trouble creating this C# method that uses generics to insert into an sqlite table
I am getting a no mapping exists error
when I try running this code. Not sure what I need to do here.
public void Create<T>(T obj) where T : IClassModel<T>
{
Type type = obj.GetType();
// get the property names and values of obj
// PropertyInfo
PropertyInfo[] properties = type.GetProperties();
for (int i = 0; i < properties.Length; i++)
{
PropertyInfo property = properties[i];
Console.WriteLine(property);
}
// build query as a string (StringBuilder)
// 1. If you aren't on the last value or column name, you need a comma
var command = _connection.CreateCommand();
// use the string you built here
command.CommandText = $"INSERT INTO {typeof(T).Name} VALUES ($Id, $FirstName, $Surname)";
command.Parameters.AddWithValue("$Id", obj).SqliteType = SqliteType.Integer;
command.Parameters.AddWithValue("$FirstName", obj).SqliteType = SqliteType.Text;
command.Parameters.AddWithValue("$Surname", obj).SqliteType = SqliteType.Text;
command.ExecuteNonQuery();
That is the create method that I am using. Please, any help is appreciated.
Setting object property by string name
Very new to typescript and am trying to port some C# code. I need to be able to set an instances properties by property string name.
In C# I do this with reflection, but how can I do this in typescript?
The following is a simplified example:
class BaseClazz {
baseA?: string;
baseB?: string;
}
class DerivedClazz extends BaseClazz {
derived1?: number;
derived2?: number;
array1?: number[];
array2?: number[];
}
I want a function that can set the various properties by their string name:
function assign(clazz: BaseClass, propertyName: string, value: any) {
...
}
In theory I can call it as follows and each of the 4 properties would be set:
test:BaseClazz = new DerivedClazz();
assign(test, "baseA", "a");
assign(test, "baseB", "b");
assign(test, "derived1", 1);
assign(test, "derived2", 2);
assign(test, "array1", [1, 2, 3, 4]);
assign(test, "array2", [5, 6, 7, 8]);
How to reflect/map models received from frontend into models at backend?
I want to make universal JSON
generator for any ViewModel
received from frontend. I found here that I can get type from string, but I do not know how to implement this in my case. My idea was to send from Angular array with 2 values, first would be string that say what type is my ViewModel
, and second value would be ViewModel
, which I need to convert to JSON
. (I need this JSON
on backend for converting to other file formats, and I have some special requirements, like change of name property, etc.) I am using MediatR
, and here are my classes: GenerateJSONQuery
is input object, the one I will get from frontend.
public class GenerateJSONQuery<T> : IRequest<string>
{
public string TypeOfList { get; set; }
public List<T> Data { get; set; }
}
GenerateJSONQueryHandler
is MediatR
handler that will do reflection to ViewModel
and generate JSON
.
public class GenerateJSONQueryHandler<T> : IRequestHandler<GenerateJSONQuery<T>, string>
{
private readonly IddeeaODPDbContext _context;
private readonly IMapper _mapper;
public GenerateJSONQueryHandler(IddeeaODPDbContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public async Task<string> Handle(GenerateJSONQuery<T> request, CancellationToken cancellationToken)
{
// logic for generating files, in this part I need to somehow convert
// `request.Data` to specific List<T> where
// T can be e.g. `NewbornByBirthDateViewModel`,
//`IssuedDocumentsViewModel`, `RegisteredVehiclesViewModel`, etc. etc.
}
Controller that connect IRequest
and IRequestHandler
is:
public class GenerateFilesController : ApiBaseController
{
public GenerateFilesController(IOptions<AppSettings> appSettings) : base(appSettings)
{
}
[HttpPost]
[SwaggerOperation(Tags = new[] { "Administration/Document" })]
public async Task<string> List<T>([FromBody] GenerateJSONQuery<T> data, [FromHeader] string Authorization)
{
return await Mediator.Send(data);
}
}
and NewbornByBirthDateViewModel
is example VieWModel
that I need to serialize into JSON
.
public class ClientNewbornByBirthDateViewModel
{
[TranslatedFieldName("Identifier", LanguageEnum.EN)]
public int Id { get; set; }
public string Institution { get; set; }
[TranslatedFieldName("Men", LanguageEnum.EN)]
public int MaleTotal { get; set; }
[TranslatedFieldName("Women", LanguageEnum.EN)]
public int FemaleTotal { get; set; }
public int Year { get; set; }
public int Month { get; set; }
}
I am pretty sure that my thinking way is bad, and that I need to do some kind of reflection, but I do not know how. I can not send only type of ViewModel
from frontend, and then select all from db
with context.Set<T>()
because there can be filters, and those filters depends on which ViewModel
is selected, so I must pass object with data from frontend to JSONGenerate
logic and then reflect it to specific ViewModel
on backend.
dimanche 20 novembre 2022
Copy EF Core entity property proxy using reflection
I am trying to make a duplicate of an EF Core entity and then store it in the database. One of the tasks is copying all writable properties. Since I have to make duplicates of many entity types, I am using reflection to copy all properties and not forgetting new ones in the future.
public abstract class BaseEntity
{
public void CopyAllWriteablePropertiesTo(BaseEntity destination)
{
Guard.ArgumentNotNull(destination, nameof(destination));
if (destination.GetUnproxiedTypeName() != this.GetUnproxiedTypeName())
throw new ApplicationException("Not same type");
var properties = this.GetType().GetProperties();
foreach (var property in properties)
{
if (property.Name == nameof(Id))
{
continue;
}
if (property.CanWrite)
{
Type memberType = property.PropertyType;
try
{
var propValue = property.GetValue(this);
var originalType = propValue.GetType();
//PROBLEMS START HERE
Convert.ChangeType(propValue, memberType);
var convertedType = propValue.GetType();
property.SetValue(destination, propValue);
}
catch (Exception ex)
{
throw new ApplicationException(ex, $"Error copying {property.Name} at object {this}");
}
}
}
}
}
With primitive types (string, int...) the process works well, but my entities have references to other entities.
I am using Lazy Loading, so when I read a property of, say DerivedEntity class,
var propValue = property.GetValue(this);
returns a proxy DerivedEntityProxy.
If I try to assign it with
property.SetValue(destination, propValue);
I get an error since types do not match ( setting a proxy object value for a raw entity).
System.Reflection.TargetException: Object does not match target type.
If before assigning I try to cast the proxy to the underlying object, I get an exception
{"Object must implement IConvertible."}
Is there a way to do this?
vendredi 18 novembre 2022
If i use Class.forName with parameter as Example.class , it throws ClassNotFoundException
First of all hello everyone and sory for my bad english :P
I have an problem with Class.forName method. If i use Class.forName with parameter as Example.class , it throws ClassNotFoundException. Then i try without class prefix for example org.example.Example and it worked. How can i solve this problem ?
My basic code and stack trace:
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Class clazz = Class.forName(String.valueOf(EventPublisherContext.class));
System.out.println(clazz.getSimpleName());
}
Exception in thread "main" java.lang.ClassNotFoundException: class org.cqs.impl.EventPublisherContext
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:390)
at java.base/java.lang.Class.forName(Class.java:381)
at org.cqs.impl.Main.main(Main.java:10)
Actually i solved this problem with basic method, in below:
public static Class getClass(Class clazz) throws ClassNotFoundException {
List<String> classString = new ArrayList<>();
String[] g = clazz.toString().split(" ");
Arrays.stream(g).forEach(val -> {
classString.add(val);
});
classString.remove(0);
return Class.forName(String.join("", classString));
}
Then i got my expect value:
public static void main(String[] args) throws ClassNotFoundException {
Class clazz = getClass(EventPublisherContext.class);
System.out.println(clazz.getSimpleName());
//print EventPublisherContext
How can i solve this problem without any additional method if it is not impossible.
Java dynamically change builtin class behaviour
I have an interesting problem. I would like to change the behaviour of some builtin class dynamically. Here is an example:
I want to change the behaviour of the "get current time" procedure in Java. I want to mock it to return 01-01-2022 12:30 if some condition is true. My intuition tells me that I need to use reflection overwriting + Proxies but I am still not sure which API can give me this flexibility. I don't know two things: What is the method that is being called to get the current time? How to "patch" method's class to be actually my Proxy?
Thanks in advance!
I checked the docs for both reflection and Proxies and I still have no clue on how to proceed.
jeudi 17 novembre 2022
How to find all classes that implement a specific interface using System.Reflection.Metadata
I'm trying to figure out whether I can reliably identify .NET assemblies that contain classes that implement a specific interface. The catch here is that I cannot load assemblies using Reflection because that requires resolving all references of the assembly to be loaded and that is just not possible in my situation.
This is why I attempt to do so using the NuGet package System.Reflection.Metadata because that approach does not seem to require loading referenced assemblies. However, I'm stuck with completing the code so that the interface in question is found. Here's what I have:
namespace ReflectionMetadataTest
{
using System;
using System.IO;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
public static class Program
{
static int Main(string[] args)
{
if (args.Length < 1)
{
Console.Error.WriteLine("Please specify a single file path.");
return 1;
}
string filePath = new FileInfo(args[0]).FullName;
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var peReader = new PEReader(fileStream))
{
if (!peReader.HasMetadata)
{
return 2;
}
MetadataReader metadataReader = peReader.GetMetadataReader();
foreach (var typeDefinitionHandle in metadataReader.TypeDefinitions)
{
var typeDefinition = metadataReader.GetTypeDefinition(typeDefinitionHandle);
var interfaceHandles = typeDefinition.GetInterfaceImplementations();
foreach (var interfaceHandle in interfaceHandles)
{
var interfaceImplementation = metadataReader.GetInterfaceImplementation(interfaceHandle);
var whateverThatIs = interfaceImplementation.Interface;
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// TODO: How would I find the fully qualified name of the the interface so that I can compare with the name I'm looking for?
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
return 0;
}
}
}
}
}
How would I resolve whateverThatIs
to an actual type of fully qualified name so that I can then compare it with the type/name of the interface that I'm looking for?
mercredi 16 novembre 2022
C#, trying to create human readable type name
I am trying to generate a human readable string for e.g. ICollection<string>
or any other generic ICollection<> / IList<> / IEnumerable<>
In order to do this I use amongst others the following routine:
public static string HumanReadableTypeName(this Type aType)
{
if (aType == null)
throw new ArgumentNullException($"{nameof(ReflectionExtensions)}.{nameof(HumanReadableTypeName)}");
var lBaseType = Nullable.GetUnderlyingType(aType);
if (lBaseType != null)
return cNullableHdr + HumanReadableTypeName(lBaseType);
if (aType == typeof(string))
return aType.Name;
if (aType.IsArray)
{
var elementTypeName = HumanReadableTypeName(aType.GetElementType());
var lBuilder = new StringBuilder(elementTypeName);
for (var i = 0; i < aType.GetArrayRank(); i++) // add brackets for each dimension
lBuilder.Append("[]");
return lBuilder.ToString();
}
var listtype = aType.GetInterfaces().Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IList<>)).FirstOrDefault();
if (listtype != null)
{
var itemType = listtype.GetGenericArguments().Single();
var itemTypeName = HumanReadableTypeName(itemType);
return $"IList<{itemTypeName}>";
}
var collectiontype = aType.GetInterfaces().Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ICollection<>)).FirstOrDefault();
if (collectiontype != null)
{
var itemType = collectiontype.GetGenericArguments().Single();
var itemTypeName = HumanReadableTypeName(itemType);
return $"ICollection<{itemTypeName}>";
}
var enumerabletype = aType.GetInterfaces().Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>)).FirstOrDefault();
if (enumerabletype != null)
{
var itemType = enumerabletype.GetGenericArguments().Single();
var itemTypeName = HumanReadableTypeName(itemType);
return $"IEnumerable<{itemTypeName}>";
}
return aType.Name;
}
Trouble is that when I pass typeof(ICollection<string>)
as an argument I get IEnumerable<string>
as an answer.
In the debugger I entered:
typeof(ICollection<string>).GetInterfaces()
with as result a collection of just 2 elements:
+ [0] {Name = "IEnumerable`1" FullName = "System.Collections.Generic.IEnumerable`1[[System.String, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]"} System.Type {System.RuntimeType}
+ [1] {Name = "IEnumerable" FullName = "System.Collections.IEnumerable"} System.Type {System.RuntimeType}
So it seems the ICollection<>
interface isn't listed!
What confuses me also is that the following statement:
typeof(ICollection<string>).Name
returns:
"ICollection`1"
So the debugger appears to be able to show it is an ICollection of some kind.
Am I overlooking something, is this featured behavior, or is it a bug in VS22 / .NET7
TIA
mardi 15 novembre 2022
Generate Avro schema from C# record
Is there a possibility to generate an Avro schema out of a C# record. I found the Avro.Reflect namespace, which has an AvroFieldAttribute to (I guess) annotate properties, but I can not figure out how to get the schema out of an annotated object.
How do you declare generic type of any "interface" in Java
Given the following example code
package com.test;
import org.reflections.Reflections;
import java.util.Set;
public class Main {
public interface TestA {}
public interface TestB {}
public static class Aclass implements TestA {}
public static class Bclass implements TestA, TestB {}
public static <T> Set<Class<? extends T>> getClassesThatImplement(Class<T> interfaceClass) {
Reflections reflect = new Reflections("com.test");
return reflect.getSubTypesOf(interfaceClass);
}
public static void main(String[] args) {
Set<Class<? extends TestA>> aClasses = getClassesThatImplement( TestA.class );
// Prints [class com.test.Main$Aclass, class com.test.Main$Bclass]
System.out.println(aClasses);
Set<Class<? extends TestB>> bClasses = getClassesThatImplement( TestB.class );
// Prints [class com.test.Main$Bclass]
System.out.println(bClasses);
}
}
how can I limit my method, getClassesThatImplement
to only accept interfaces so that I get compile time errors instead of runtime errors if I use a regular class? There is no common, or "root", interface I can use to "bound" my generic type <T implements ...>
. Is there even a way to do that in Java or will I have to rely on runtime checks?
lundi 14 novembre 2022
Adding to a Generic List with Type parameter
Consider the following setup:
class Shelf : ScriptableObject // << IS A SCRIPTABLE OBJECT
{
[SerializeField] List<Jars> jars = new();
public AddUniqueJar(Type typeOfJar)
{
//need to add a new object of type typeOfJar to jars. I currently do something like this:
sentences.Add((FlipbookSentence)Activator.CreateInstance(typeOfJar));
EditorUtility.SetDirty(this);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
abstract class Jar:UnityEngine.Object{} // << NOT A SCRIPTABLE OBJECT
class JamJar:Jar{}
class PickleJar:Jar{}
class MoneyJar:Jar{}
I'd have imagined this would all be fine but the next time my code compiles or restart a session my object forgets what Type of Jar each instance within the list is, or that the instance is anything at all as I'm met with a null reference.
How do I get my method to add a new object of this type to the list while also serializing and maintaining that information between sessions?
what's the benefit to use TypeInfo api over Type or vice versa?
I was looking at the example of the article below https://devblogs.microsoft.com/dotnet/evolving-the-reflection-api/ and still don't quite understand it, below is the quote:
Suppose that we are using a static analysis tool that is implemented with the new reflection model. We are looking for all types in an app that derive from the UIControl class. We want to be able to run this tool on workstations on which the UIControl assembly (which contains the UIControl class) does not exist. In this example, let’s assume that we open an assembly that contains a class that derives from the UIControl class:
class MyClass : UIControl
In the .NET Framework 4 reflection model, the Type object (incorporating both reference and definition) that represents MyClass would create a Type object for the base class, which is UIControl. On machines that don’t have the UIControl assembly, the request to construct the UIControl Type object would fail, and so too would the request to create a Type object for MyClass, as a result.
Here you see what the reference/definition split achieves. In the new model, MyClass is a TypeInfo (definition); however, BaseType is a Type (reference), and will contain only the information about UIControl that the (MyClass) assembly contains, without requiring finding its actual definition.
Type baseType = myClassTypeInfo.BaseType;
so I did some experiments, I created an console application and two class libraries, one contains UIControl.dll and the other contains MyClass.dll, and MyClass.dll references UIControl.dll (via Visual Studio's Add Project Reference) then I copied the MyClass.dll into a new location (so CLR can't find UIControl.dll) and make console application references to this MyClass.dll simulate that "UIControl assembly (which contains the UIControl class) does not exist on workstations" as the article mentioned.
but when I tried to use Type api or TypeInfo api, it always throwed FileNotFoundException saying it couldnot load UIControl assembly:
// Console app that reference MyClass.dll
// note that this dll is coped into a new location
// so CLR can't find its referencing UIControl.dll
internal class Program
{
Type type = typeof(MyClass); // throw FileNotFoundException
TypeInfo typeInfo = typeof(MyClass).GetTypeInfo(); // throw FileNotFoundException
}
so how does the author gets the TypeInfo
instance (myClassTypeInfo) without throwing FileNotFoundException?
dimanche 13 novembre 2022
Is there any metadata reader compatible with reflection?
I want to get the declarative security attributes from an assembly. For now i just go through all the types in assembly and all of their members to look for custom attributes that derive from CodeAccessSecurityAttribute. This works kinda fine, but i think the better way is to read the DeclSecurity metadata table and get the attributes from there. But the problem is that all the cool reflection metadata things are on different net platforms, i need something for .NET Framework 4.8. I know there is dnlib but it uses its own classes for everything so using it together with reflection will be hard to say the least
mercredi 9 novembre 2022
Using a type variable how can I specify the type of a constructor argument passed to Activator.CreateInstance?
This is NOT a question about generics.
Suppose I have a class with constructor public MyClass(int myParam){}
.
And I want to construct it with Activator.CreateInstance
when I have:
- the
Type
ofMyClass
in a variableclassType
, - the
Type
ofmyParam
in a variableparamType
, - the value to pass as
myParam
in a variablemyValue
BUT it is an object.
I want to do this
public void CreateTheClass(Type classType, Type paramType, object myValue)
{
return Activator.CreateInstance(classType, myValue);
}
But this will throw an exception because the constructor takes an int
, not an object
. I don't believe it is possible to cast myValue
to an int
because the type (specified by paramType
) is in a type variable.
Is there a way to tell Activator.CreateInstance
to treat myValue
as a different type? Is it possible to use a dynamic for this? Is there an alternative approach?
mardi 8 novembre 2022
How to Invoke a static method and provide only some of optional parameters?
This is my static class containing a static method:
public static class TS
{
public static bool act(string s, string t = "def", int id = 0)
{
return true;
}
}
And this is how I invoke it somewhere in the code:
string name = "act";
typeof(TS).GetMethod(name).Invoke(null, new object[] { "foo", "bar" });
Note that the first optional parameter is given but the second one is not. if I provide them all it works just fine but now I get this exception:
Exception thrown: 'System.Reflection.TargetParameterCountException' in mscorlib.dll
Additional information: Parameter count mismatch.
How do I tell it to use the default values for some of optional parameters?
lundi 7 novembre 2022
why does Java not guarantee ordering in Class.getDeclaredFields() and similar methods
The Java documentation is very careful to state that Class.getDeclaredFields() and similar methods make no guarantees about method ordering. There are a few exceptions: it's easy to get declaration order for enum
s and for record
components, and a few other semi-obscure things. But not for methods or fields. My questions is: WHY? It seems to me that it's cheap for Java to guarantee declaration order, and it's obviously sometimes useful, so it seems to be a pure win. Is there a catch I'm missing?
EF Core: How to get identity key value generically using reflection or keyattribute
Good day, currently working on an existing system that has over a 200 lookups which are stored in the database, e.g.
public class FruitLookup
{
[Key]
public int FruitId {get;set;}
public string FruitCode {get;set;}
public string Description {get;set;}
}
Each lookup has a code and description accordingly and each has a strategy class to get its data and only the code and description is exposed as below:
public class FruitLookupStrategy : LookupStrategy
{
public IQueryable<LookupBase> GetLookupData()
{
return this.GetLookupData()
.Select(_ => new LookupDataSet
{
Code = _.FruitCode,
Description = _.Description
})
.OrderBy(_ => _.Value)
.AsQueryable();
}
}
public class LookupBase
{
public int Id {get;set;} // new mapping property added
public string Code {get;set;}
public string Description {get;set;}
}
this.GetLookupData...
is just an EF call to select the lookup table. It exists in the base class LookupStrategy
The new requirement is to expose the Id for each of these lookup tables, because codes can be the same, and we the Id properties will be mapped on our new front ends as the value expressions.
Is there a way to achieve this in a more clever way that going to edit over 200 lookup strategy helper files either using generics or reflection? Below is the undesired approach of adding a new mapping of Id to each strategy class:
public class FruitLookupStrategy : LookupStrategy
{
public IQueryable<LookupBase> GetLookupData()
{
return this.GetLookupData()
.Select(_ => new LookupDataSet
{
Code = _.FruitCode,
Description = _.Description,
Id = _.FruitId
})
.OrderBy(_ => _.Value)
.AsQueryable();
}
}
dimanche 6 novembre 2022
How do I instantiate a generic DAO class using reflection?
I have been trying to instantiate a generic DAO class. The problem is that I have a Class<?>
class. It can be Client or Worker, so I can't specify which class is it. I tried instantiating the DAO class with Class<?>
, but the DAO wont work right since I am using reflection on DAO to find out the fields the class used in generics have.
I need to do something like this.
DAO dao = new DAO<this.gerindo.getClass()>();
vendredi 4 novembre 2022
Reflection - Retrieve implementation information from the Functional Interface [duplicate]
I have the following class:
public class RequestInterceptorFilter implements HandlerFilterFunction<ServerResponse, ServerResponse> {
@Override
public Mono<ServerResponse> filter(ServerRequest request, HandlerFunction<ServerResponse> handlerFunction) {
long startTime = System.currentTimeMillis();
try {
return handlerFunction.handle(request);
} finally {
LOGGER.debug("Executed in {}", (System.currentTimeMillis() - startTime));
}
}
}
In this class, the second argument of the filter
method is a Functional Interface coming from the framework I have used. From the source code it is:
@FunctionalInterface
public interface HandlerFunction<T extends ServerResponse> {
Mono<T> handle(ServerRequest request);
}
During the execution, I have placed a breakpoint in the filter
method and inspected the arguments. What I can see is shown below: I would like to retrieve the arg$1, which is UserClaimRetrievalRequestHandler@12249
within the filter
method.
Is there any way I can do that?
jeudi 3 novembre 2022
MakeGenericMethod For Max Is Not Working In .Net 6
So we recently migrated our project from .net framework 4.7.2 to .net 6 and we are testing the code for any issues , while testing i found out that the following method for Max is not working in .net 6
var maxOfStringMethod = (from method in typeof(Enumerable).GetMethods()
where method.Name == "Max"
&& method.GetParameters().Length == 2 &&
method.GetParameters()[1].ParameterType.GenericTypeArguments[1].IsGenericParameter
select method).First().MakeGenericMethod(new Type[] { typeof(SomeViewModel), typeof(string) });
Above code method is for "TResult Max[TSource,TResult](System.Collections.Generic.IEnumerable1[TSource], System.Func
2[TSource,TResult])".
It was working fine in .net framework 4.7.2 , but while testing the migrated code in .net 6 it throws "ArrayOutOfBoundsException" So i tried changing the above code to following for getting same result from Enumerable methods in .Net 6
var maxOfStringMethod = (from method in typeof(Enumerable).GetMethods()
where method.Name == "Max"
&& method.GetParameters().Length == 2 &&
method.GetParameters()[0].ParameterType.GenericTypeArguments[0].IsGenericParameter
select method).ElementAt(1).MakeGenericMethod(new Type[] { typeof(SomeViewModel), typeof(string) });
Now it's throwing "System.ArgumentException: 'The type or method has 1 generic parameter(s), but 2 generic argument(s) were provided. A generic argument must be provided for each generic parameter.' " I dont know what to do to solve this next , any help will be much appreciated
How get class by name with generic or how correct realize this problem?
I want dinamycally load catalogs to DevExpress grid and repositories. Some columns reference to other tables. I want to realize without "if-else, switch" methods, solve with generic for example. My project consists of entity framework, unitofwork etc.
RepositoryItemLookUpEdit repositoryItemLookUpEdit = new RepositoryItemLookUpEdit()
{
ValueMember = repositoryItem.ValueMember,
DisplayMember = repositoryItem.DisplayMember
;
// var objectType = GetTypeByName(repositoryItem.FinalTable);
if (repositoryItem.FinalTable=="DeviceTypes")
{
objectList = GetObjectList<DeviceTypes>();
}
else if (repositoryItem.FinalTable == "DeviceKinds")
{
objectList = GetObjectList<DeviceKinds>();
}
repositoryItemLookUpEdit.DataSource = objectList;
bandedGridColumn.ColumnEdit = repositoryItemLookUpEdit;
---
private IEnumerable<T> GetObjectList <T>() where T : Entity
{
IEnumerable<T> objectList=Enumerable.Empty<T>();
using (var unitOfWork = new UnitOfWork(new ApplicationDbContext(optionsBuilder.Options)))
{
objectList = unitOfWork.GetRepository<T>().GetAll();
}
return objectList;
}
---
private T GetTypeByName<T>(string typeName) where T:Entity
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Reverse())
{
var type = assembly.GetType(typeName);
if (type != null)
{
return type as T;
}
}
return null;
}
mercredi 2 novembre 2022
Check if a value of a property is null or default from reflected properties of a model [duplicate]
I want to perform some action if a value of a property is default or null by reflection. The following code gives "is a variable but is used like a type error" on default(t).
foreach(var p in dummyModel.GetType().GetProperties())
{
var value = p.GetValue(dummyModel,null);
var t = p.PropertyType;
if(value != default(t)
{
//some action here
}
}
mardi 1 novembre 2022
Using reflection is it possible to get a collection of types by namespace then use them in a generic system?
To be clear, I'm not looking for "How do you get a type from an object", I'm asking how to use a generic Type to also create a generic class.
Using the below code I'm looking to reference my classes within the "Foo" namespace and be able to use them again in my generic system:
var types = Assembly.GetExecutingAssembly().GetTypes().Where(t => String.Equals(t.Namespace, "Foo", StringComparison.Ordinal)).ToArray();
What I would like to be able to do, is:
public class Bar<T>
{
...
}
...
foreach (Type T in types)
{
//Create a generic Bar with T
//Something like new Bar<T>();
}
Is the current way I'm going about it the proper way and if so what would be the best way to handle Bar in this case?
In Java, detect if an Object is a Kotlin array
Sorry if this is very specific...
I am looking at Javapoet's implementation of AnnotationSpec.get(Annotation)
. It recursively clones an annotation so that you can copy it to another element. In my case, I am trying to copy an @OpenApi
annotation from one method to another.
The issue is caused by the annotations being written in kotlin. Anywhere the annotation needs a class, it is using KClass<*>
. Javapoet only handles Java types, like Class<?>
. From Java, I can say if (o instanceof Class || o instance of KClass)
no problem.
However, there's also code that says o.getClass().isArray()
but, from what I can tell, kotlin annotations use Array<*>
for arrays, so that check is failing. The actual type appears to be com.sun.proxy.$Proxy54
when I inspect it, but I have no idea what that is.
How do you detect if an object is an kotlin array from Java? Can this be converted to a Java array? Is there some universal way to make kotlin annotations appear as java annotations using Class
and built-in arrays and so on?
How do I add java files at runtime and compile them during runtime?
I have to check whether a method exists or not in a java class but this java file is not present in the current classpath.
for example
I am running a java code then I have to check presence of java method which is not present in current project(i.e those java files are not compiled) those java files are present at a different location.
My Approach:
1. Adding those files to class path
2. compling each java file
3. then checking the presence of methods in a class specified
Codes:
public static void setClassPath(String path) {
String cp = System.getProperty("java.class.path");
cp = cp.replace(";.;", "");
System.out.println("Before >>>>>>>>>>>>>>>>" + cp);
String newcp = cp + System.getProperty("path.separator") + path;
System.setProperty("java.class.path", newcp);
System.out.println("After>>>>>>>>>>>>>>>>" + System.getProperty("java.class.path"));
}
public static void compileJavaFile() {
// Compile source file.
for (File f : javaFiles) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, f.getAbsolutePath());
}
}
public static boolean isMethodExist(String className, String methodName) {
Class<?> classToCheck = null;
try {
classToCheck = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return false;
}
try {
Method[] declaredMethods = classToCheck.getDeclaredMethods();
for (Method method : declaredMethods) {
if (method.getName().equals(methodName)) {
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return false;
}
C# EF Core reflection order
I would kindly ask you for help.
When I have queryable such as
var query = dbSet.AsQueryable();
and I would like to dynamicly set orderBy using reflection
var orderBy = "School.Name"
query = query.OrderBy("School.Name");
var data = await query.ToListAsync()
I do have extension to support order like this using reflection as following:
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName)
{
return source.OrderBy(ToLambda<T>(propertyName));
}
private static Expression<Func<T, object>> ToLambda<T>(string propertyName)
{
var parameter = Expression.Parameter(typeof(T));
var property = Expression.Property(parameter, propertyName);
var propAsObject = Expression.Convert(property, typeof(object));
return Expression.Lambda<Func<T, object>>(propAsObject, parameter);
}
Problem is to create lambda for inner object property such as School.Name. This solution works for Name attribute on Dbset object, but not on joinned.
Goal is to modify ToLambda method to support joinned or inners properties.
using
query.OrderBy("School.Name");
// instead of
query.OrderBy(m => m.School.Name );
Thanks for your help.