Привет. У меня всегда были проблемы с решениями выше (и на других сайтах). Я, как разработчик, программирую аддон для API. API разрешает использование любых внешних библиотек или сторонних инструментов. Установка также состоит из смеси кода в jar или zip-файлах и файлах классов, расположенных непосредственно в некоторых каталогах. Таким образом, мой код должен был работать на всех настройках. После большого количества исследований я придумал метод, который будет работать, по крайней мере, на 95% всех возможных настроек.
Следующий код - это в основном метод переполнения, который всегда будет работать.
Этот код сканирует данный пакет для всех классов, включенных в него. Он будет работать только для всех классов в текущем ClassLoader
.
/**
* Private helper method
*
* @param directory
* The directory to start with
* @param pckgname
* The package name to search for. Will be needed for getting the
* Class object.
* @param classes
* if a file isn't loaded but still is in the directory
* @throws ClassNotFoundException
*/
private static void checkDirectory(File directory, String pckgname,
ArrayList<Class<?>> classes) throws ClassNotFoundException {
File tmpDirectory;
if (directory.exists() && directory.isDirectory()) {
final String[] files = directory.list();
for (final String file : files) {
if (file.endsWith(".class")) {
try {
classes.add(Class.forName(pckgname + '.'
+ file.substring(0, file.length() - 6)));
} catch (final NoClassDefFoundError e) {
// do nothing. this class hasn't been found by the
// loader, and we don't care.
}
} else if ((tmpDirectory = new File(directory, file))
.isDirectory()) {
checkDirectory(tmpDirectory, pckgname + "." + file, classes);
}
}
}
}
/**
* Private helper method.
*
* @param connection
* the connection to the jar
* @param pckgname
* the package name to search for
* @param classes
* the current ArrayList of all classes. This method will simply
* add new classes.
* @throws ClassNotFoundException
* if a file isn't loaded but still is in the jar file
* @throws IOException
* if it can't correctly read from the jar file.
*/
private static void checkJarFile(JarURLConnection connection,
String pckgname, ArrayList<Class<?>> classes)
throws ClassNotFoundException, IOException {
final JarFile jarFile = connection.getJarFile();
final Enumeration<JarEntry> entries = jarFile.entries();
String name;
for (JarEntry jarEntry = null; entries.hasMoreElements()
&& ((jarEntry = entries.nextElement()) != null);) {
name = jarEntry.getName();
if (name.contains(".class")) {
name = name.substring(0, name.length() - 6).replace('/', '.');
if (name.contains(pckgname)) {
classes.add(Class.forName(name));
}
}
}
}
/**
* Attempts to list all the classes in the specified package as determined
* by the context class loader
*
* @param pckgname
* the package name to search
* @return a list of classes that exist within that package
* @throws ClassNotFoundException
* if something went wrong
*/
public static ArrayList<Class<?>> getClassesForPackage(String pckgname)
throws ClassNotFoundException {
final ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
try {
final ClassLoader cld = Thread.currentThread()
.getContextClassLoader();
if (cld == null)
throw new ClassNotFoundException("Can't get class loader.");
final Enumeration<URL> resources = cld.getResources(pckgname
.replace('.', '/'));
URLConnection connection;
for (URL url = null; resources.hasMoreElements()
&& ((url = resources.nextElement()) != null);) {
try {
connection = url.openConnection();
if (connection instanceof JarURLConnection) {
checkJarFile((JarURLConnection) connection, pckgname,
classes);
} else if (connection instanceof FileURLConnection) {
try {
checkDirectory(
new File(URLDecoder.decode(url.getPath(),
"UTF-8")), pckgname, classes);
} catch (final UnsupportedEncodingException ex) {
throw new ClassNotFoundException(
pckgname
+ " does not appear to be a valid package (Unsupported encoding)",
ex);
}
} else
throw new ClassNotFoundException(pckgname + " ("
+ url.getPath()
+ ") does not appear to be a valid package");
} catch (final IOException ioex) {
throw new ClassNotFoundException(
"IOException was thrown when trying to get all resources for "
+ pckgname, ioex);
}
}
} catch (final NullPointerException ex) {
throw new ClassNotFoundException(
pckgname
+ " does not appear to be a valid package (Null pointer exception)",
ex);
} catch (final IOException ioex) {
throw new ClassNotFoundException(
"IOException was thrown when trying to get all resources for "
+ pckgname, ioex);
}
return classes;
}
Эти три метода предоставляют вам возможность находить все классы в данном пакете. Вы используете его следующим образом:
getClassesForPackage("package.your.classes.are.in");
Метод сначала получает текущий ClassLoader
. Затем он извлекает все ресурсы, содержащие указанный пакет, и итерации этих URL
s. Затем он создает URLConnection
и определяет тип URl, который у нас есть. Это может быть либо каталог (FileURLConnection
), либо каталог внутри jar или zip-файла (JarURLConnection
). В зависимости от типа соединения мы будем вызывать два разных метода.
Сначала давайте посмотрим, что произойдет, если это FileURLConnection
. Сначала он проверяет, существует ли переданный файл и является ли он каталогом. Если это так, он проверяет, является ли это файлом класса. Если это так, то объект Class
будет создан и помещен в ArrayList
. Если это не файл класса, а каталог, мы просто повторяем его и делаем то же самое. Все остальные случаи / файлы будут игнорироваться.
Если URLConnection
является JarURLConnection
, будет вызван другой метод private helper. Этот метод выполняет итерацию по всем записям в архиве zip / jar. Если одна запись является файлом класса и находится внутри пакета, объект Class
будет создан и сохранен в ArrayList
.
После того, как все ресурсы были проанализированы, он (основной метод) возвращает ArrayList
содержит все классы в данном пакете, о которых знает текущий ClassLoader
.
Если процесс завершается с ошибкой в любой момент, а ClassNotFoundException
будет зависеть от подробной информации о конкретной причине.
Я ответил подобный вопрос только что. В основном лучший способ состоял бы в том, чтобы использовать класс HttpValueCollection
, который QueryString
на самом деле свойство, к сожалению, это является внутренним в платформе.NET. Вы могли использовать Отражатель, чтобы захватить его (и поместить его в Ваш класс Utils). Таким образом, Вы могли управлять строкой запроса как NameValueCollection, но со всеми проблемами кодирования/декодирования URL, заботившимися для Вас.
HttpValueCollection
расширяется NameValueCollection
и имеет конструктора, который берет закодированную строку запроса (амперсанды и включенные вопросительные знаки), и она переопределяет ToString()
метод для позже восстановления строки запроса от базового набора.
Лично я предпочитаю переписывать запрос или работать с namevaluecollection на более низком уровне, но бывают случаи, когда бизнес-логика не делает ни один из них очень полезным, и иногда рефлексия действительно то, что вам нужно . В таких обстоятельствах вы можете просто на мгновение отключить флаг «только для чтения»:
// reflect to readonly property
PropertyInfo isreadonly = typeof(System.Collections.Specialized.NameValueCollection).GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
// make collection editable
isreadonly.SetValue(this.Request.QueryString, false, null);
// remove
this.Request.QueryString.Remove("foo");
// modify
this.Request.QueryString.Set("bar", "123");
// make collection readonly again
isreadonly.SetValue(this.Request.QueryString, true, null);
Да, нет никаких классов, встроенных в.NET для редактирования строк запроса. Необходимо будет или использовать Regex или некоторый другой метод изменения самой строки.
Вы, вероятно, собираетесь хотеть, используют Регулярное выражение для нахождения параметра, который Вы хотите удалить из querystring, затем удалить его и перенаправить браузер в тот же файл с Вашим новым querystring.
Получите querystring набор, проанализируйте его в (name=value pair
) строка, исключая ту, которую Вы хотите УДАЛИТЬ, и назвать им, newQueryString
Тогда звонит Response.Redirect(known_path?newqueryString)
;
Если это - HttpRequest. QueryString тогда можно скопировать набор в перезаписываемый набор и иметь путь с ним.
NameValueCollection filtered = new NameValueCollection(request.QueryString);
filtered.Remove("Language");
Вы не проясняете, пытаетесь ли Вы изменить Querystring на месте в объекте Запроса. Так как то свойство только для чтения, я предполагаю, что мы предположим, что Вы просто хотите смешать со строкой.
... В этом случае это - тривиальная граница.
Наконец,
ответ hmemcpy был полностью для меня и благодаря другим друзьям, которые ответили.
я захватываю HttpValueCollection с помощью Отражателя и написал следующий код
var hebe = new HttpValueCollection();
hebe.Add(HttpUtility.ParseQueryString(Request.Url.Query));
if (!string.IsNullOrEmpty(hebe["Language"]))
hebe.Remove("Language");
Response.Redirect(Request.Url.AbsolutePath + "?" + hebe );