返回过载失败 [英] Return overload fails

查看:67
本文介绍了返回过载失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注以下内容: https://github.com/Readify/Neo4jClient /wiki/cypher ,但我是通过Powershell进行的.所以我到目前为止是

[System.Reflection.Assembly]::LoadFrom("C:\...\Newtonsoft.Json.6.0.3\lib\net40\NewtonSoft.Json.dll")
[System.Reflection.Assembly]::LoadFrom("C:\...\Neo4jClient.1.0.0.662\lib\net40\Neo4jClient.dll")

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

,我的意思是检索数据库中的所有节点.在示例中显示了Return()方法需要一个lambda表达式作为参数,在Powershell中它将是一个代码块,但是,出现以下错误:

找不到"Return"和参数计数:"1"的重载.在 行:1字符:1 + $ q = $ neo.Cypher.Match("n").Return({param($ m)$ m}); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo:未指定:(:) [],MethodException + FullyQualifiedErrorId:MethodCountCouldNotFindBest

我要去哪里错了?

*更新我*

通过下面@PetSerAl提供的解释,我可以进一步了解,但是我仍然很困惑.在下面,我将引用写的内容(c#),然后显示等效的powershell.首先我们声明一个类

public class User
{
    public long Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}

我的班级略有不同

Add-Type -TypeDefinition "public class Project { public string Code; public string Name; public string Parent; public string Lifespan; }"

他们的密码

MATCH (user:User)
RETURN user

他们的c#

graphClient.Cypher
    .Match("(user:User)")
    .Return(user => user.As<User>())
    .Results

现在是我的密码

MATCH (n:Project)
RETURN n

...最后,我尝试使用Powershell:

$exp = [System.Linq.Expressions.Expression]
$p = $exp::Constant("Project")
$fn = $exp::TypeAs($p, (new-object Project).GetType())
$return = $exp::Lambda([Func[Project]], $fn, $p)
$neo.Cypher.Match("n").Return($return)

但是我得到一个错误

以"1"作为参数调用"Return"的异常:表达式必须 被构造为对象初始值设定项(例如:n => new MyResultType {Foo = n.Bar}),一个匿名类型初始值设定项( 例如:n => new {Foo = n.Bar}),一个方法调用(例如:n => n.Count())或成员访问器(例如:n => n.As().Bar). 您无法提供代码块(例如:n => {var a = n + 1; 返回}或使用带参数的构造函数(例如:n => new Foo(n)).如果您使用的是F#,则还支持元组.参数名称: 表达式"在线:1字符:1 + $ neo.Cypher.Match("n").Return($ return) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo:未指定:(:) [],MethodInvocationException + FullyQualifiedErrorId:ArgumentException

这实际上是非常清楚和可以理解的.所以我想要的是一个方法调用n => n.Count()显然没有达到目标.

帮助?

*更新II *

因此,继续从powershell到neo4j的曲折道路,我给@PetSerAl的第二种方法做了一次尝试,然后进一步介绍了它.这是我设法写的:

$neopath = "C:\[...]\Neo4jClient.dll"
Add-Type -ReferencedAssemblies $neopath -TypeDefinition @"
    using System;
    using System.Linq.Expressions;
    using Neo4jClient.Cypher;
    public class Project {
        public string Code;
        public string Name;
        public string Parent;
        public string Lifespan;
    };
    public static class NeoExp {
        public static readonly Expression<Func<Neo4jClient.Cypher.ICypherResultItem,Project>> GetProject = (n) => n.As<Project>();
}
"@

现在,我可以这样做:

$neo.Cypher.Match("n:Project").Return([NeoExp]::GetProject)

这奇迹般地起作用了!只是它没有带我回来任何数据:

Results ResultsAsync Query                         Client 
------- ------------ -----                         ------                                                                      
                     Neo4jClient.Cypher.CypherQ... Neo4jClient.GraphClient

而且我知道我的数据库中有项目...所以现在可能是什么问题?

*更新III *

哇,太近了,但还没有完成.根据@PetSerAl的最新建议.我试过了:

$neo.Cypher.Match("n:Project").Return([NeoExp]::GetProject).get_Results()

这产生了一个照明错误:

使用"0"作为参数调用"get_Results"的异常:图形 客户端未连接到服务器.首先调用Connect方法."

所以我首先需要做的很清楚:

$neo.Connect()

另外,我需要在查询的match子句周围加上括号:

$neo.Cypher.Match("(n:Project)").Return([NeoExp]::GetProject)

现在我在.Results字段中获得了27个预期的结果...但是,结果全部为空白.所以我认为这可能与n.As<Project>()有关,其中我的班级定义不正确而失败了.有什么想法吗?

*更新IV *

好,知道了. Project类需要具有属性,而不是字段:

    public class Project {
        public string Code { get; set; }
        public string Name { get; set; }
        public string Parent { get; set; }
        public string Lifespan { get; set; }
    };

就是这样.我有资料是的!

@PetSelAl:我欠你一杯啤酒

解决方案

感谢@PetSerAl,他从本质上很好地解释了这个问题,并通过解决方案握住了我的手.

要重新声明,问题是Powershell没有内置的机制来调用通用方法,而Neo4jClient库的.Return方法重载都是通用的.具体来说,Powershell无法提供方法的类型.

所以有几种方法可以解决这个问题:

  • 一种解决方案是使用反射进行调用,但是此任务有些棘手.值得庆幸的是,该方法已经通过技术网上的一个项目得以解决.请参阅: https://gallery.technet.microsoft.com/scriptcenter/调用通用方法-bf7675af

  • @PetSerAl的答复中建议的第二种解决方案需要一点帮助,但是在@ChrisSkardon的帮助下,它才起作用.参见此处:构造方法调用

  • 和第三个解决方案(请参阅原始文章中的更新),该解决方案依赖于使用一种可以调用通用方法的方法创建c#类

我希望能在Neo4jClient的Wiki中记录此解决方案,并希望此处记录的工作对其他人有帮助.再次感谢@PetSerAl提供的所有帮助

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.Reflection.Assembly]::LoadFrom("C:\...\Newtonsoft.Json.6.0.3\lib\net40\NewtonSoft.Json.dll")
[System.Reflection.Assembly]::LoadFrom("C:\...\Neo4jClient.1.0.0.662\lib\net40\Neo4jClient.dll")

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

with which I would mean to retrieve all nodes in the database. the Return() method is shown in the example to require a lambda expression as a parameter, which in Powershell would be a code-block, however, I get the following error:

Cannot find an overload for "Return" and the argument count: "1". At line:1 char:1 + $q=$neo.Cypher.Match("n").Return({param($m) $m}); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodCountCouldNotFindBest

where am I going wrong?

* Update I *

with the explanation provided by @PetSerAl below, I've managed to get a little further, but I'm still stuck. below I will quote the write up (c#) and then show the equivalent powershell. first we declare a class

public class User
{
    public long Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}

my class differs a little

Add-Type -TypeDefinition "public class Project { public string Code; public string Name; public string Parent; public string Lifespan; }"

their Cypher

MATCH (user:User)
RETURN user

their c#

graphClient.Cypher
    .Match("(user:User)")
    .Return(user => user.As<User>())
    .Results

now my cypher

MATCH (n:Project)
RETURN n

...and finally, my attempt at the powershell:

$exp = [System.Linq.Expressions.Expression]
$p = $exp::Constant("Project")
$fn = $exp::TypeAs($p, (new-object Project).GetType())
$return = $exp::Lambda([Func[Project]], $fn, $p)
$neo.Cypher.Match("n").Return($return)

but I get an error

Exception calling "Return" with "1" argument(s): "The expression must be constructed as either an object initializer (for example: n => new MyResultType { Foo = n.Bar }), an anonymous type initializer (for example: n => new { Foo = n.Bar }), a method call (for example: n => n.Count()), or a member accessor (for example: n => n.As().Bar). You cannot supply blocks of code (for example: n => { var a = n + 1; return a; }) or use constructors with arguments (for example: n => new Foo(n)). If you're in F#, tuples are also supported. Parameter name: expression" At line:1 char:1 + $neo.Cypher.Match("n").Return($return) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : ArgumentException

which, for once, is actually very clear and understandable. so what I want is a method call e.g. n => n.Count() and clearly did not achieve that.

help?

* Update II *

so, continuing on with the torturous path of neo4j from powershell, I've given @PetSerAl's second approach a stab and got a little further. here's what I managed to write:

$neopath = "C:\[...]\Neo4jClient.dll"
Add-Type -ReferencedAssemblies $neopath -TypeDefinition @"
    using System;
    using System.Linq.Expressions;
    using Neo4jClient.Cypher;
    public class Project {
        public string Code;
        public string Name;
        public string Parent;
        public string Lifespan;
    };
    public static class NeoExp {
        public static readonly Expression<Func<Neo4jClient.Cypher.ICypherResultItem,Project>> GetProject = (n) => n.As<Project>();
}
"@

which now allows me to do:

$neo.Cypher.Match("n:Project").Return([NeoExp]::GetProject)

and that, miraculously, works! except it brings me back no data:

Results ResultsAsync Query                         Client 
------- ------------ -----                         ------                                                                      
                     Neo4jClient.Cypher.CypherQ... Neo4jClient.GraphClient

and I know I have projects in the database... so what could the issue be now?

* Update III *

wow, so close but still not done. as per the latest suggestion from @PetSerAl. I tried:

$neo.Cypher.Match("n:Project").Return([NeoExp]::GetProject).get_Results()

which yielded an illuminating error:

Exception calling "get_Results" with "0" argument(s): "The graph client is not connected to the server. Call the Connect method first."

so that made it clear I first needed to do:

$neo.Connect()

also, I needed parentheses around the query's match clause:

$neo.Cypher.Match("(n:Project)").Return([NeoExp]::GetProject)

now I get 27 results back as expected in the .Results field... however, the results are all blank. so I think maybe it has to do with the n.As<Project>() where perhaps my class isn't defined properly and that fails. any thoughts?

* Update IV *

ok, got it. the Project class needs to have properties, not fields:

    public class Project {
        public string Code { get; set; }
        public string Name { get; set; }
        public string Parent { get; set; }
        public string Lifespan { get; set; }
    };

and that's it. I have data. yea!!!

@PetSelAl: I owe you a beer

解决方案

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

这篇关于返回过载失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆