lundi 15 avril 2019

Constructor.newInstance replaces Scala object

I was debugging a deserialization issue with Jackson where Scala object instances seemed to be replaced. I managed to drill the issue down to this code:

object WaitWhat extends App {

  object XX

  val x1 = XX

  // Notice: no assignment!
  XX.getClass.getConstructor().newInstance()

  val x2 = XX

  println(x1)
  println(x2)
}

The output is:

WaitWhat$XX$@5315b42e
WaitWhat$XX$@2ef9b8bc

(Of course the actual hash codes change each run.)

IntelliJ's debugger also indicates that x1 and x2 really are different instances, despite the fact that the result of newInstance is completely ignored.

I would have expected a no-op, or an exception of some kind. How is it possible that the actual object instance gets replaced by this call?





Gettting the argument types of a constructor using Data and Typeable

I'm playing around with Haskell's Data and Typeable, and I'm stuck trying to get the arguments of a function without a type variable being available in the context.

Let me clarify what I mean. As long as I have the type variable a quantified like below, I can use fromConstr and obtain a list of DataType or TypeRep as I wish:

constrArgs :: forall a. Data a => Constr -> [DataType]
constrArgs c = gmapQ f (fromConstr c :: a)
  where f :: forall d. Data d => d -> DataType
        f _ = dataTypeOf @d undefined

(I realize the undefined and fromConstr are nontotal but laziness saves us here.)

However, if I try to avoid quantifying a, I can no longer do a type ascription to the result of fromConstr. I wonder if there is a way to write a function with the following type signature:

constrArgs' :: Constr -> [DataType]

My end goal is to write a function that gives a list of lists of DataTypes, a sublist for each constructor, each sublist containing the argument types of that constructor. Using the first version, it's not difficult to write a function with the type signature: (definition elided)

allConstrArgs :: forall a. Data a => [[DataType]]

The problem with this is that I cannot apply allConstrArgs to the results of itself, because there is no way to go from DataType to a type-level value.

So, in order to amend that, can we write a function that has the following type?

allConstrsArgs' :: DataType -> [[DataType]]

I looked around in the base library but I'm failing to see how this can be achieved.





Can't get a list of declared methods in a .net class

Having read a great many posts on using reflection to get a list of methods in a given class, I am still having trouble getting that list and need to ask for help. This is my current code:

Function GetClassMethods(ByVal theType As Type) As List(Of String)
    Dim methodNames As New List(Of String)
    For Each method In theType.GetMethods()
        methodNames.Add(method.Name)
    Next
    Return methodNames
End Function

I call this method like this:

GetClassMethods(GetType(HomeController))

The return has 43 methods, but I only want the methods I wrote in the class. The image below shows the beginning of what was returned. My declared methods are in this list, but down at location 31-37. There are actually 9 declared methods, but this list doesn’t show the Private methods.

enter image description here

When I look at theType, I see the property I want. It is DeclaredMethods which shows every declared method, public and private.

enter image description here

However, I’m not able to access this property with a statement such as this.

Dim methodList = theType.DeclaredMethods()

The returned error is that DelaredMethods is not a member of Type. So, my questions are multiple:

1) Most important, what code do I need to retrieve every declared method in the class, and only the methods I declared?

2) Why am I not able to access the property that gives the list of DeclaredMethods()?





kotlin, map a class to another class

I'm creating an API rest and I need it when I do "find ALL" instead of fetching all the data, I just fetch a few. With Java I did it this way:

 @GetMapping(value = "/pagina")
    public ResponseEntity<Page<PersonFindDTO>> findAll(
            @RequestParam(value = "page", defaultValue = "0") Integer page,
            @RequestParam(value = "linesPerPage", defaultValue = "24") Integer linesPerPage,
            @RequestParam(value = "order", defaultValue = "ASC") String order,
            @RequestParam(value = "orderBy", defaultValue = "name") String orderBy) {


        var person = personService.findAll(page, linesPerPage, order, orderBy);

        var personFindDto = person.map(PersonFindDTO::new);

        return ResponseEntity.ok().body(personFindDTO);
    }

With Kotlin, I'm trying this way:

   @GetMapping(value = ["/{companyId}/{active}"])
    override fun findAll(
            @RequestParam(value = "page", defaultValue = "0") page: Int,
            @RequestParam(value = "linesPerPage", defaultValue = "24") linesPerPage: Int,
            @RequestParam(value = "order", defaultValue = "ASC") order: String,
            @RequestParam(value = "orderBy", defaultValue = "tradeName") orderBy: String,
            @PathVariable companyId: Long, @PathVariable active: Boolean): ResponseEntity<Page<Any>> {

        val lp = service.findAll(page, linesPerPage, order, orderBy, companyId, active)?.let {
            it.map {
                fun LegalPerson.toLegalPersonMPage() = LegalPersonMPage(id = it.id,
                        tradeName = it.tradeName, companyName = it.companyName, cnpj = it.cnpj)
            }
        }
        return ResponseEntity.ok().body(lp)
    }

But the return is always empty. Could anyone help? Please.





Convert a JSON object/string to a C# dynamic object and have access to the properties/values?

I am trying to take a huge JSON file (could be a string) and without knowing the actual structure of the data I want to read and process it as a class in C#. I tried using JSON to deserialize it but I wasn't totally sure about where to go after that. I was thinking of using Reflections but not sure what data I need.

I have tried to deserialize the object as the code shows. But I want to test if it is the right object type incase it isn't I would hope it fails but I can't seem to get past this part. I also am not sure what to do with reflections inside of the check. I know I should iterate but not sure which property values inside of the object will contain what I need.

string jsonData = sr.ReadToEnd();
dynamic data = JsonConvert.DeserializeObject(jsonData);
if (data is List<dynamic>)
{
    data.GetType().GetProperties();
}

I want an object that has all the access to the data from a JSON file/string.





When I reflect objects of an external assembly in the T4 template,System.IO.FileNotFoundException

For example, I want to generate the template in assembly Mall.T4 by reflecting the objects in assembly Mall.Data. But I met System. IO. FileNotFoundException: failed to load file or assembly 'Microsoft. EntityFrameworkCore. Relational, Version = 2.2.3.0, Culture = neutral, PublicKeyToken = adb9793829ddae60 "or one of its dependencies. The specified file could not be found.The file name: "Microsoft. EntityFrameworkCore. Relational, Version = 2.2.3.0, Culture = neutral, PublicKeyToken = adb9793829ddae60"problem

I tried joining Microsoft in the current assembly. EntityFrameworkCore. Relational. DLL, and references in the T4 template. But it didn't work.

<#@ template language="C#" debug="True" #>
<#@ output extension="txt" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="EnvDTE" #>
<#@ assembly name="$(TargetDir)Microsoft.EntityFrameworkCore.dll" #>
<#@ assembly name="$(TargetDir)Microsoft.EntityFrameworkCore.Relational.dll" #>
<#@ assembly name="$(TargetDir)Mall.Component.dll" #>
<#@ assembly name="$(TargetDir)Mall.Data.dll" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="Mall.Component.UnitOfWork" #>
<#@ import namespace="Mall.Data.AccountData" #>
<#@ include file="T4Toolbox.tt" #>
<#@ include file="ServiceTemplate.tt" #>
<#@ include file="IServiceTemplate.tt" #>
<#@ include file="RepositoryTemplate.tt" #>
<#@ include file="IRepositoryTemplate.tt" #>
<#
    string curPath = Path.GetDirectoryName(Host.TemplateFile);
    string destPath = Path.Combine(curPath, "CodeFiles");
    if(!Directory.Exists(destPath))
    {
        Directory.CreateDirectory(destPath);
    }
    try
    {
        var assemblyEntity = typeof(Mall).Assembly;
        var assemblyEntityTypesInfo = assemblyEntity.DefinedTypes.Where(m => m.BaseType == typeof(DataBase)).ToList();
        foreach (var typeInfo in assemblyEntityTypesInfo)
        {
            var moduleName=typeInfo.Namespace.Split('.').LastOrDefault();//文件名前缀
            var modelName=moduleName.Substring(0, moduleName.Length - 4) + "Context";//数据库仓储名
            var tableName=typeInfo.Name;//数据库表名
            //IRepository生成
            CSharpTemplate template = new IRepositoryTemplate(moduleName,modelName,tableName);
            string fileName = string.Format(@"{0}\{2}Repository\{1}.cs", destPath, "I"+tableName+"Repository", moduleName);
            template.Output.Encoding = Encoding.UTF8;
            template.RenderToFile(fileName);
            //Repository生成
            template = new RepositoryTemplate(moduleName,modelName,tableName);
            fileName = string.Format(@"{0}\{2}Repository\Impl\{1}.cs", destPath, tableName+"Repository", moduleName);
            template.Output.Encoding = Encoding.UTF8;
            template.RenderToFile(fileName);
            //IService生成
            template = new IServiceTemplate(moduleName, tableName);
            fileName = string.Format(@"{0}\{2}Service\{1}.cs", destPath, "I"+tableName+"Service", moduleName);
            template.Output.Encoding = Encoding.UTF8;
            template.RenderToFile(fileName);
            //Service生成
            template = new ServiceTemplate(moduleName, tableName);
            fileName = string.Format(@"{0}\{2}Service\Impl\{1}.cs", destPath, tableName+"Service", moduleName);
            template.Output.Encoding = Encoding.UTF8;
            template.RenderToFile(fileName);
        }
    }
    catch(ReflectionTypeLoadException ex)
    {
        foreach(var exception in ex.LoaderExceptions)
        { #>
            <#=exception#>
        <#}
    }
#>





dimanche 14 avril 2019

Mocking an API response type

I have function which accepts an Oracle Jolt ServletResult. I'm looking to unit test this function to verify that it correctly uses the data that it's been passed. ServletResult has a protected Constructor and the objects seem to be created internally in Jolt by a Factory.

I've tried Mocking the ServletResult, but that almost requires re-implementing it. The other option I was thinking about was using reflection to create the object. It seems though that Spring ReflectionTestUtils doesn't seem to handle constructors.

What is the best way to deal with this sort of thing? Should such tests just be left to integration testing rather than unit testing?