Страницы

Поиск по вопросам

пятница, 26 октября 2018 г.

Когда используются собственные домены приложений?

Прочитал про домены приложений и немного не понял, при каких обстоятельствах следует грузить сборки в отдельный домен.
Как я понял, по функционалу это похоже на стандартную динамическую загрузку библеотек(позднее связывание), но с одним отличием- домены изолированы между собой и для взаимодействия нужно использовать какой-либо протокол взаимодейсвтия (Например, WCF).
Я правильно понимаю, что это что-то типа: Приложения, которое содержит в себе N-ое кол-во других изолированных приложений?


Ответ

Есть несколько сценариев, при которых нужны домены.
Например, это выполнение кода непонятного происхождения. Если ваше приложение грузит плагин из интернета, то в нём может оказаться враждебный код. Вы можете вынести его в другой домен с урезанными правами, чтобы он не имел доступа к файловой системе, P/Invoke или рефлексии.
Далее, если код не злонамеренный, но просто «падучий», то опять-таки есть смысл выгрузить его в отдельный домен, чтобы при падении он не «утащил» за собой главное приложение.
Следующий сценарий упомянут @Alexander Petrov в комментарии: вы не можете выгрузить загруженную сборку, но можете выгрузить целый домен. Выгрузка сборки может быть нужна, чтобы удалить файл с ней (например, вы хотите загрузить новую версию плагина).
Ещё один сценарий — вы можете таким образом избавиться от очень большого статического объекта. (С точки зрения языка статический объект живёт вечно, но на самом деле он будет выгружен вместе с доменом.)

Обновление версии Android приложения - как?

Залил в PlayMarket приложение, доработал его, хочу залить ОБНОВЛЕНИЯ. Создал новый APK файл программы где в манифесте указал:



При загрузке АРК файла выдает ошибку "APK-файл с кодом версии 1 уже существует. Используйте другой код." Как обновить?


Ответ

Версию надо менять НЕ В МАНИФЕСТЕ а в файле build.gradle !!!!!!

Разница между вызовом методов класса и структур

Имеется такая ситуация
struct Point { int x; int y; public void SetX(int a){ ... } public void SetY(int a){ ... } } class A { Point cord = new Point(); public Point Cord { get { return cord; } } public void MethodA(int a) { cord.SetX(a); //здесь все ок } }
class B { A myObj = new A(); public Point Cord { get { return cord; } } public void MethodB(int a) { myObj.Cord.SetX(a); //а здесь не присваивает значение } }
В классе А метод отрабатывает верно, а в классе B нет( заходит в метод , где то чему то значение присваивает , но в объекте myObj и в его поле cord типа Point нет) Интересно чему все таки это значение присваивается и почему с классами работает, а со структурой нет.


Ответ

Потому что структура это ValueType и копируется полностью.
В результате вызова
get { return cord; }
Будет новый объект структуры, в котором ты и вызываешь метод SetX

Выбор чисел Фибоначчи

Задача не практическая. Хочется оценить, какими подходами ее можно решить на SQL'ях разных диалектов (PostgreSQL, SQLite3, MySQL). И как сложно это решаемо.
Задача
Есть таблица с положительными числами [0..N]. Нужно вывести в порядке возрастания все числа из указанной таблицы, которые входят в последовательность Фибоначчи


Ответ

Генератор без использования таблиц для SQLite, postgresql:
WITH Recursive Q(Num,Prev) as( select 1,1 union all select Q.Num+Q.Prev,Q.Num from Q where Q.Num<10000 ) select Num from Q
Если надо выбрать из них только те числа, что есть в некой таблице - то в итоговый select добавить join с этой таблицей для проверки наличия числа в ней.
Для MS SQL и Oracle - убрать из запроса выше фразу Recursive. Для Oracle дополнительно добавить from DUAL после select 1,1
Для MySQL требуется опорная таблица с нужным количеством записей, содержимое этих записей значения не имеет:
select @tmp:=@Prev+@Num as Num, @Prev:=@Num, @Num:=@tmp from seqnum, (select @Prev:=1, @Num:=1) A order by Num
Это опять же генератор. Для проверки наличия в некой таблице - заключить в подзапрос и сделать join.

Как сделать перемещение нод TreeView?

Ветки нужно перемещать ноды на уровень выше в материнские и ниже в дочерние.
Моё дерево:
>

На другом примере работает нормально но в моём нет.
1 -2 --3 4 -5 --6
У меня любую ноду можно переместить в корень или в ту же ноду, в которой и находится. Например 3 можно переместить в корень либо в 2, где он уже есть.
В другие почему-то не перемещается.
public class Node { public string name_ { get; set; }
public ObservableCollection collection_node { get; set; }
public Node() {
collection_node = new ObservableCollection(); } }


Ответ

Рекомендую использовать GongSolutions.WPF.DragDrop, которую можно легко установить добавив соответствующий NuGet-пакет.
Дальше к своему TreeViewпросто добавляете два свойства:

где dd
xmlns:dd="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop"
Теперь вы можете легко перетаскивать элементы:

Взятие адреса у массива

Всем известно что имя массива это адрес первого элемента в массиве, но все было бы так просто если бы не взятие адреса у имени массива.
Есть такое объявление массива: char array[] = "String";
Если мы пишем: array или &array[0] - мы получаем адрес первого элемента в массиве первый вариант - неявный, второй - явный.
Я подумал хм, а что если я напишу &array - на первый взгляд ничего странного адрес тот же что и у array или &array[0], но если чучуть закопаться по-глубже, то есть &array+1 - мы увидим что адрес увеличится на длину строки (для меня это странно, никогда этого не видел, кроме как в параметрах, когда аргументом был указатель на массив элементов определенного количества, прям как сейчас)
Интересно есть ли альтернатива такому поведению (&array)? Я пока что додумался до такого способа: (char (*)[sizeof(array)])array - но правильно ли это?
Помимо этого интересно следущее поведение: Если мы пишем *array мы получим элемент массива ровно как и array[0], но если мы напишем *(&array) - мы не получим элемент массива, мы получим тот же самый адрес, который указывает на первый элемент, но с той лишь разницей что его адресаная арифметика упала с целого массива до одного символа.
Можно ли сказать что в данном случае это разименование указателя до уровня указателя на символ (такой своеобразный даунгрейд указателя)?
И что вообще происходит с массивом когда мы пишем *(&array) на ваш взгляд?


Ответ

Если у вас есть указатель вида
T *p;
то 1) для арифметики указателей используется значение sizeof( T ), и 2) разыменование указателя дает lvalue , на который указывает указатель.
Например, если имеется следующий фрагмент кода
int a[] = { 1, 2 }; int *p = &a[0];
то значение указателя после выполнения выражения ++p будет равно
значение указателя перед инкрементом плюс значение sizeof( int )
В этом случае в результате указатель будет указывать на элемент a[1]
Если имеется объявление следующего массива
char array[] = "String";
то оно эквивалентно следующему объявлению массива
char array[7] = "String";
Если ввести typedef объявление
typedef char T[7];
то объявление вышеприведенного массива можно записать также как
T array = "String";
Поэтому чтобы объявить указатель на этот объект, следует записать
T *p = &array;
И, как показано выше, для арифметики указателей для указателя p используется выражение sizeof( T ) , которое равно sizeof( char[7] )
Разыменовывая этот указатель, вы получите lvalue объекта типа char[7]
Это легко проверить, выполнив предложение
printf( "%zu
", sizeof( *p ) );
результатом которого будет значение 7, то есть получена длина массива типа char[7]
Однако когда в качестве объекта, полученного после разыменования указателя, имеется массив, то он в выражения за редким исключением преобразуется к указателю на свой первый элемент.
Из стандарта C (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
Поэтому для вышеприведенного примера если выражение *p, не используется в качестве операнда оператора sizeof или оператора &, то происходит неявное преобразование полученного массива в указатель на свой первый элемент. Поэтому, например, выражение **p даст объект типа char со значением 'S'

Как оценить простоту использования ПО?

Возникла задача оценить простоту использования программы, причем не просто "сложно-просто", а более объективно... Может быть есть какие-нибудь системы оценки, которые дают конкретное число, оценивающее простоту, скажем по 10-и бальной шкале или что-то в этом роде. Буду благодарен за помощь. (извиняюсь за офф-топ, не знал, какие теги указать :))


Ответ

Чтобы объективно оценить простоту использования программы, посадите за нее пользователя, который видит ее впервые. Дайте пользователю задание (или несколько), которое он должен выполнить самостоятельно с помощью этой программы. Замерьте время выполнения. Это и будет объективная оценка простоты использования программы