mercredi 31 mai 2023

DynamicForm Component that takes Generic Model Class as Parameter to Generate EditForm

I have a component called DynamicForm which accepts couple of Parameters including Generic Model Class.

@typeparam TModel

<EditForm Model="@Model" OnValidSubmit="@HandleFormSubmit">
    @foreach (var property in typeof(TModel).GetProperties())
    {
        @if (property.PropertyType == typeof(string))
        {
            <input class="form-control" id="@property.Name" @bind="@property.GetValue(Model)" />
        }
        else if (property.PropertyType == typeof(DateTime))
        {
            <input type="date" class="form-control" id="@property.Name" @bind="@property.GetValue(Model)" />
        }
    }

    <button type="submit" class="btn btn-primary">Submit</button>
</EditForm>

@code {
    [Parameter]
    public TModel Model { get; set; }

    [Parameter]
    public EventCallback<TModel> OnValidSubmit { get; set; }

    private Task HandleFormSubmit()
    {
        return OnValidSubmit.InvokeAsync(Model);
    }
}

what I am trying to achive is to generate Dynamic EditForm (Controls) based on Provided Model Class using following code

<DynamicForm TModel="FormModel" Model="@person" OnValidSubmit="HandleFormSubmit" />

@code {
    private FormModel person = new FormModel();

    private void HandleFormSubmit(FormModel model)
    {
        //Todo
    }
}

But I am getting following compile time errors on @bind="@property.GetValue(Model)"

  • Error (active) CS0131 The left-hand side of an assignment must be a variable, property or indexer
  • Error (active) CS1503 Argument 1: cannot convert from 'object' to 'System.DateTime'




mardi 30 mai 2023

In .NET 6.0/7.0, how to load an assembly and then delete the assembly file?

In .NET 6.0, I loaded an assembly and invoked its methods and properties using reflection, then tried to delete the assembly file:

    var dllFilePath = @"C:\Users\frank\source\repos\.NET core\MyDll\bin\Debug\net6.0\MyDll.dll";
    var ctx = new AssemblyLoadContext(null, isCollectible: true);
    var assembly = ctx.LoadFromAssemblyPath(dllFilePath);
    var myType = assembly.GetType("MyDll.MyClass");
    var instance = Activator.CreateInstance(myType, new object[] { }, null);
    var myMethod = myType.GetMethod("GetGuidText");
    var res = myMethod.Invoke(instance, new object[] { Guid.NewGuid() });

    ctx.Unload();
    myType = null;
    instance = null;
    myMethod = null;
    ctx = null;
    assembly = null;

    GC.Collect();
    GC.WaitForPendingFinalizers();
    Thread.Sleep(2000);
    GC.Collect();
    GC.WaitForPendingFinalizers();

    File.Delete(dllFilePath);

The attempt to delete threw exception:

System.UnauthorizedAccessException: 'Access to the path 'C:\...\MyDll\bin\Debug\net6.0\MyDll.dll' is denied.'

How do I delete this file without having to restart the app?





lundi 29 mai 2023

Use of ReflectionTestUtils.setField() in Junit testing to set a List of objects

in my implementation , i have

List<recordEntity> entityList = service.mapper(parameter1,parameter2);

i need to set the value for this entityList with a static value for my unit testing, i know that using ReflectionsTestUtils we can set value, even i have used this for another scenaro,

ReflectionTestUtils.setField(classObject, "implementations", Collections.singletonMap("mapper", new DTOMapper()));

but am not sure how to set a list





how to edit method annotation attributes on runtime in springboot project?

how to edit method annotation attributes on runtime in springboot project? i've known there's a way to edit by using reflection like invocationHandler.getClass().getDeclaredField("memberValues"); but in the newer springboot environment it doesn't work, cause the invocationHandler that i got is not the instance of AnnotationInvocationHandler but the instance of SynthesizedMergedAnnotationInvocationHandler, in SynthesizedMergedAnnotationInvocationHandler i cant find the method that let me change the value of the annotation fields on the fly,thx in advance

i'm trying to reused the way that worked in old version just like:


InvocationHandler invocationHandler = Proxy.getInvocationHandler(rateLimit);
Field field = invocationHandler.getClass().getDeclaredField("memberValues");
field.setAccessible(true);
Map params = (Map)field.get(invocationHandler);
params.put("fields1",xxx);

but there's no fields called 'memberValues'





dimanche 28 mai 2023

C# Assembly Resolve Context problems

I'm loading an Assembly that references to TPL.DataFlow library and I was having problems because TPL.DataFlow dll was not loading. As I have read in Microsoft Documentation when using Assembly.LoadFrom() the folder of the assembly is taking in consideration in the Assembly Load Context.

I have solved the problem using the AssemblyResolve event but it's extrange that in debugging I have seen that the if (assembly == null) condition is not reached, so the assembly was loaded in context but not resolved.

Even that I have solved the problem I was surprised about that and that is why I'm asking about AssemblyResolve context

public static IService LoadService(CtorParameters parameters)
{
    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
        CurrentDomain_AssemblyResolve(sender, args, parameters.DllLocation);
    try
    {
        var assembly = Assembly.LoadFrom(parameters.DllLocation);
        var serviceType = assembly.GetType(SERVICE_TYPE);
        var serialPortInstance = (IService)Activator.CreateInstance(serviceType, parameters);
        return serialPortInstance;
    }
    finally
    {
        AppDomain.CurrentDomain.AssemblyResolve -= (sender, args) =>
            CurrentDomain_AssemblyResolve(sender, args, parameters.DllLocation);
    }
}

private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args, string loadedAssemblyPath)
{
    var appDomain = (AppDomain)sender;
    if (args.RequestingAssembly == null)
    {
        try
        {
            var assemblyName = new AssemblyName(args.Name);
            var assembly = appDomain.GetAssemblies().FirstOrDefault(m => m.GetName().Name == assemblyName.Name);
            if (assembly == null)
            {
                var loadedDllDir = Path.GetDirectoryName(loadedAssemblyPath);
                var dllPath = Path.Combine(loadedDllDir, $"{assemblyName}.dll");
                assembly = Assembly.LoadFrom(dllPath);
            }
            return assembly;
        }
        catch { }        
    }
    return args.RequestingAssembly;
}




vendredi 26 mai 2023

Retrieving whole C# class implementation as a string in code [duplicate]

How to retrieve whole class in C# as a string.

What I mean by that is:

This is my class

public class MyClass
{
    public int MyProperty { get; set; }

    public void MyMethod()
    {
        Console.WriteLine("Inside MyMethod");
        Console.WriteLine("Hello, World!");
        Console.ReadLine();
    }
}

And I would like to output this implementation as a string.

Console.WriteLine(MyClassString)

Expected result:

"""public class MyClass
{
    public int MyProperty { get; set; }

    public void MyMethod()
    {
        Console.WriteLine("Inside MyMethod");
        Console.WriteLine("Hello, World!");
        Console.ReadLine();
    }
}"""




System.InvalidProgramException Common Language Runtime detected an invalid program for Reflection

System.InvalidProgramException : Common Language Runtime detected an invalid program. Seeing this error message whilst trying to check the expression's correctness and if it is the correct IL.

The expression is "DateTimeA.GetType().Name", where we expect the result to be a string i.e. "String;DateTimeA.GetType().Name;String".

This is an example from "ValidExpressions.txt" using mparlak's "Flee" (see https://github.com/mparlak/Flee/blob/master/src/Flee/).

For some reason, the code is failing on that specific expression. I've checked what the emitted ops are and it goes as follows...

ldarg.0
ldfld
callvirt
callvirt
ret

length 17

I've run the test on the Flee library (as the .txt file was in the tests but the test was previously removed), and it fails with this error. Not entirely sure how to resolve it... I expect this test to pass with no problems but it appears that the "GetType()" method specifically is causing problems and I'm not sure why...