Я видел много плохого кода, написанного на эту тему. Код, который работал для меня, - это (сайт не знает, как правильно проанализировать мой файл кода):
public class Test {
public static boolean isReachablebyPing(String ip) {
try {
String command;
if(System.getProperty("os.name").toLowerCase().startsWith("windows")) {
// For Windows
command = "ping -n 2 " + ip;
} else {
// For Linux and OSX
command = "ping -c 2 " + ip;
}
Process proc = Runtime.getRuntime().exec(command);
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
outputGobbler.start();
proc.waitFor();
return checkAvailability(outputGobbler.getOutputLines());
} catch(IOException | InterruptedException ex) {
Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
public static void main(String... args) {
String ip = "10.20.20.17"; // false in my case
String ip1 = "10.20.20.100"; // true in my case
System.out.println(ip + " is avalaible " + isReachablebyPing(ip));
System.out.println(ip1 + " is avalaible " + isReachablebyPing(ip1));
}
private static boolean checkAvailability(List<String> outputLines) {
for(String line : outputLines) {
if(line.contains("unreachable")) {
return false;
}
if(line.contains("TTL=")) {
return true;
}
}
return false;
}
}
class StreamGobbler extends Thread {
protected InputStream is;
protected String type;
protected List<String> outputLines;
StreamGobbler(InputStream is, String type) {
this.is = is;
this.type = type;
outputLines = new ArrayList<>();
}
public List<String> getOutputLines() {
return outputLines;
}
@Override
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while((line = br.readLine()) != null) {
outputLines.add(line);
}
} catch(IOException ex) {
Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Другой способ - использовать предикат Expression
...
var query = from x in table where SomeFunctionReturnsBool() select;
Изменить: Я обычно не делаю этого способ, который я показал выше ... Я только что понял это из кода выше. Вот как я обычно это реализую. Потому что тогда вы можете добавить дополнительные методы Enumerable или закомментировать их во время отладки.
var results = table.Where(SomeFunctionReturnsBool())
.OrderBy(yt => yt.YourProperty)
//.Skip(pageCount * pageSize) //Just showing how you can easily comment out parts...
//.Take(pageSize)
.ToList(); //Finally executes the query...
private Expression<Func<YourType, boo>> SomeFunctionReturnsBool()
{
return (YourType yt) => yt.YourProperty.StartsWith("a")
&& yt.YourOtherProperty == true;
}
Я предпочитаю использовать PredicateBuilder , который позволяет вам создать выражение, которое будет использоваться в вашем Where ...
Это можно сделать в LINQ-to-SQL, создав UDF, сопоставленный с контекстом данных; для этого нужно написать TSQL и использовать ctx.SomeFunctionblah (...).
Альтернативой является работа с деревьями выражений - например, это может быть:
Expression<Func<Customer, bool>> SomeFunc() {
return c => true; // or whatever
}
и использование .Where (SomeFunc ())
- это достаточно близко? В этом случае вы не можете использовать синтаксис запроса, но он выполняет свою работу ...
Добавлен хитрый метод Where
, чтобы показать, как вы можете использовать его в синтаксисе запроса . Я не полагаю, что это фантастика, но вы можете найти это удобным.
using System;
using System.Linq;
using System.Linq.Expressions;
static class Program
{
static void Main()
{
using (var ctx = new NorthwindDataContext())
{
ctx.Log = Console.Out;
// fluent API
var qry = ctx.Customers.Where(SomeFunc("a"));
Console.WriteLine(qry.Count());
// custom Where - purely for illustration
qry = from c in ctx.Customers
where SomeFunc("a")
select c;
Console.WriteLine(qry.Count());
}
}
static IQueryable<T> Where<T>(this IQueryable<T> query,
Func<T, Expression<Func<T, bool>>> predicate)
{
if(predicate==null) throw new ArgumentNullException("predicate");
return query.Where(predicate(default(T)));
}
static Expression<Func<Customer, bool>> SomeFunc(string arg)
{
return c => c.CompanyName.Contains(arg);
}
}
По сути, «из коробки» у вас не может быть LINQ-to-SQL для выполнения запросов, содержащих пользовательские функции. Фактически можно использовать только некоторые собственные методы, которые могут быть переведены в SQL.
Самый простой способ обойти это, к сожалению, может повлиять на производительность в зависимости от того, сколько данных вы возвращаете из БД.
В принципе, вы можете только используйте пользовательские функции в статусах WHERE, если данные уже были загружены в память, т. е. SQL уже был выполнен.
Самое быстрое исправление для вашего примера будет выглядеть так:
var query = from x in table.ToList() where SomeFunctionReturnsBool() select;
Обратите внимание на ToList (). Он выполняет SQL и помещает данные в память. Теперь вы можете делать все, что хотите, в операторе / методе WHERE.
Я бы просто разбил их так:
Expression<Func<Table, bool>> someTreeThatReturnsBool = x => true;
var query = from x in table where someTreeThatReturnsBool select x;
Вы можете создавать функции, которые передают деревья выражений.
Не используйте для этого синтаксис запроса.
var query = table.Where( x => SomeFunction(x) );