Return overload fails

后端 未结 4 1328
独厮守ぢ
独厮守ぢ 2021-01-20 01:34

I\'m following this little write up: https://github.com/Readify/Neo4jClient/wiki/cypher but I\'m doing it from Powershell. so what I have so far is

[System.         


        
相关标签:
4条回答
  • 2021-01-20 02:04

    I know this is not exactly what you're asking, and might not even be what you want, but you could create your own C# class right inside PowerShell using Add-Type. It might be easier to implement it that way and provide simple methods you can use within the PowerShell code if what you're writing relies on a lot of C#-specific things.

    This example is taken straight from the link above:

    $source = @"
    public class BasicTest
    {
      public static int Add(int a, int b)
      {
        return (a + b);
      }
      public int Multiply(int a, int b)
      {
        return (a * b);
      }
    }
    "@
    Add-Type -TypeDefinition $source
    [BasicTest]::Add(4, 3)
    $basicTestObject = New-Object BasicTest
    $basicTestObject.Multiply(5, 2)
    
    0 讨论(0)
  • 2021-01-20 02:09

    There are two problems with Return method:

    1. It accepts argument of expression tree type, rather then compiled delegate type. And PowerShell does not have an easy way to create expression tree from a ScriptBlock. So, you have to create expression tree by hands or use string overload.
    2. string overload does not allows PowerShell to infer generic parameter for method, and PowerShell syntax does not allows to specifying generic parameter explicitly. So, PowerShell can not call string overload of Return method directly. You have to use some workaround to call it, for example, call it thru Reflection.

    Sample how can you create a simple expression tree ((a,b) => a*2+b) in PowerShell:

    # First way: messing with [System.Linq.Expressions.Expression]
    $a=[System.Linq.Expressions.Expression]::Parameter([int],'a')
    $b=[System.Linq.Expressions.Expression]::Parameter([int],'b')
    $2=[System.Linq.Expressions.Expression]::Constant(2)
    
    $Body=[System.Linq.Expressions.Expression]::Add([System.Linq.Expressions.Expression]::Multiply($a,$2),$b)
    $Sum=[System.Linq.Expressions.Expression]::Lambda([Func[int,int,int]],$Body,$a,$b)
    $Sum
    
    # Second way: using help of C#
    Add-Type -TypeDefinition @'
        using System;
        using System.Linq.Expressions;
        public static class MyExpression {
            public static readonly Expression<Func<int,int,int>> Sum=(a,b) => a*2+b;
        }
    '@
    [MyExpression]::Sum
    
    0 讨论(0)
  • 2021-01-20 02:15

    The best I can tell is that you're using it wrong. Your object structure should be your Neo4jClient object, which should then have a few properties and methods. I am pretty sure that Return is a property, not a method. So I'm thinking something more like:

    $neo = new-object Neo4jClient.GraphClient(new-object Uri("http://localhost:7474/db/data"))
    $neo.Cypher.Match = "n"
    $neo.Cypher.Return = {param($m) $m}
    $q = $neo.Cypher.Results()
    

    There you create your object, you define the Match filter, define what you want it to return (everything from the looks of it), and then store the results in the $q variable. I'm pretty sure that should be the same as:

    SELECT * FROM Uri("http://localhost:7474/db/data")) WHERE "n"
    

    I also kind of wonder about your Match criteria, since they seem to be specifying property/value pairs in their examples and you just give one of the two. If that fails I would strongly suggest doing a $neo.Cypher | Get-Member to see what properties you have, what they're typed as, and what methods you have.

    Edit: Ok, so I did look at the link. I also downloaded the libraries, loaded them into PowerShell, and looked at the .Net objects. Return is indeed a method, and the overloads for it are ridiculous. There are 37 overloads for it, the longest of which is almost 750 characters. Most of them are ICypherResultItem expressions, but the simplest is (string identity). Might I suggest simply trying Return("*")?

    0 讨论(0)
  • 2021-01-20 02:20

    a million thanks to @PetSerAl who explained the problem well in its essence, and who held my hand through its resolution.

    to restate, the problem is that Powershell has no built-in mechanism to call generic methods and the Neo4jClient library's .Return method overloads are all generic. Specifically, Powershell provides no means of supplying the type of the method.

    so there are several ways to solve this:

    • one solution is to use reflection to make the call, but the task is a bit tricky. thankfully the approach has been tackled by a project available on tech net. see: https://gallery.technet.microsoft.com/scriptcenter/Invoke-Generic-Methods-bf7675af

    • the second solution suggested in @PetSerAl's reply needed a little help but with @ChrisSkardon's help I got it to work. see here: Constructing a method call

    • and the third solution (see the Updates in the original post) which relies on creating a c# class with a method where the generic method can be called

    I expect to be documenting this solution in the wiki for Neo4jClient and I hope the effort documented here is helpful to others. Thanks again @PetSerAl for all your help

    0 讨论(0)
提交回复
热议问题