20.01.2018 Разные экземпляры одной сборки
 
Всем привет!

Вопрос больше для наших экспертов, так что в первую очередь хочется услышать ответы Nikov-а, Sinix-а и т.п.

Введение

Если в Розлиновском компиляторе/движке IDE создать два разных проекта (в одном солюшене) и дать в них ссылки на две одноименных и одноверсионных сборок но содержащих разные типы или сигнатуры (т.е. отличающихся по содержимому), то он спокойно с этим работает. В одном проекте видна одна сигнатура. В другом, другая. Правда при сборке и запуске получается исключение о несовпадении сигнатур, так при компиляции в output-каталог кладется одна из этих сборок (видимо они затирают друг друга), а дотнет спокойно резолвит вторую сорку в первую, так как у них совпадает идентити. Но если по колдовать, то таки можно добиться корректной работы такой программы.

В дотнете сложно загрузить сборку с одинаковой идетнити (с одинаковыми: именем + версией + и без пабик токена) в один и тот же AppDomain. Однако с помощью события AppDomain.CurrentDomain.AssemblyResolve, метода Assembly.LoadFile и какой-то матери мне удалось загрузить два ОДИНАКОВЫХ типа из двух одноименных и одноверсионных сборок (положенных в два подкаталога). При этом сами типы отличались. У них были одноименные функции с разными сигнатурами.

Предисловие

При построении деревьев пространств имен и типов (в компиляторе или движке IDE) можно идти двумя путями:

1. Загрузить отдельно каждую сборку построив дерево пространств имен только для этой сборки и потом построить по ним общее дерево типов для каждого проекта. При этом можно загружать сборки вне контекста конкретного проекта. Если два проекта ссылаются на одну сборку, то они будут разделять символы (типы, пространства имен и т.п.) из одинаковых сборок.

2. Загружать сборки в деревья пространств имен и типов каждого проекта в отдельности. При этом получится создать иерархии в которых одна и та же сборка ссылается на типы из одинаковых по имени и версии, но разных по содержанию сборок.

Преимущество пути 1 заключается в том, что символы не дублируются для каждого проекта. А это значит что будет экономиться память и процедура проектного поиска поиска символов упрощается. Каждый проект будет просто ссылаться на один и тот же символа.

Так же первый путь позволяет легко реализовать такие фишки как глобальные алиасы C# (пример: global::SomeNamespace.SomeType).

Но при выборе пути 1 не удастся иметь разные по содержимому, но одинаковые по идедентити (имени + версии + пабик токену) сборки в составе разных проектов. Ведь внутри типов есть ссылки на типы из референс-сборок. Если грузим сборку только один раз, то физически не может создать иерархию для двух разных по содержанию референсных сборок.

В общем-то такое может получиться только по глупости разработчиков не поменявших версии у разных по содержанию сборок. Но физически то это возможно.

Второй путь неприятен тем, что у нас получаются несвязанные наборы символов для каждого проекта. А это не только потери памяти, но и трудности в поиске символов в рамках всего солюшена.

Вопрос 1

Собственно вопрос в том насколько разумно выбирать первый подход (с однократной загрузкой символов для сборок в рамках всего солюшена)?

Как бы очень хочется. Но колется.

Вопрос 2

Может быть можно сделать некий промежуточный вариант в котором при наличии одинаковой иерархии референсных сборок можно будет иметь одинаковую иерархию и создавать параллельные иерархии в ином случае.

ЗЫ

Не уверен, что объяснил все понятно. Если что задавайте уточняющие вопросы.

19.01.2018 Почему Convert.ToDateTime (Int64) не реализован?
 
В общем-то мелочь, но захотелось логику применения узнать, вдруг чего-то не понимаю.
В описании на msdn прямо сказано, что Convert.ToDateTime (Int64) фактически не реализован.

https://msdn.microsoft.com/ru-ru/library/400f25sk(v=vs.110).aspx

При вызове этого метода всегда возникает исключение InvalidCastException.


Неясно почему MS решили ввести этот метод еще в версии 1.1 дотнета, но похоже, что навсегда оставить ошибку преобразования, при том, что есть конструктор DateTime от Int64, и в принципе всегда можно написать, что-то вроде нижеследующего и оно работает.

Int64 a;
....
Console.WriteLine(new DateTime(a).ToLongDateString());


Так делают иногда для делегатов или если подразумевается, что метод будет переписан в унаследованном классе, но тут, смысла не вижу.

19.01.2018 Как сделать проверку при закрытии окна в рамках MVVM?
 
Приветствую.

Есть окно. При его закрытии нужно спрашивать пользователя, хочет ли он этого и не закрывать окно, если не хочет. Как это реализовать в категориях MVVM? Т.е., наверно, нужно откуда-то достать признак хотим ли мы закрывать окно при закрытии окна. Подскажите, пожалуйста, где его найти? Я реализовал это так, после выполнения команды независимо от результата диалога окно закрывается. Поправьте меня пожалуйста:
<Window ...
             SizeToContent="WidthAndHeight"
             WindowStartupLocation="CenterScreen" 
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Closing">
            <i:InvokeCommandAction Command="{Binding Path=WWindowClosingCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
...
</Window>

    public class ViewModelClass : Notifier,IViewModel
    {
        #region переменные
        /// <summary>объект модели private</summary>
        private IModel model;
        /// <summary>объект модели public</summary>
        public IModel Model { get { return model; } }
        /// <summary>команда закрытия формы private</summary>
        private ICommand wWindowClosingCommand;
        /// <summary>команда закрытия формы public</summary>
        public ICommand WWindowClosingCommand { get { return wWindowClosingCommand; } set { wWindowClosingCommand = value; NotifyPropertyChanged("WWindowClosingCommand"); } }
        #endregion
        #region функции
        /// <summary>конструктор класса ViewModelClass</summary>
        /// <param name="_model">объект модели</param>
        public ViewModelClass(IModel _model)
        {
                model = _model;

                WWindowClosingCommand= new WindowClosingCommandClass(this);
        }
        ...
        #endregion
    }

    /// <summary>команда закрытия формы</summary>
    public class WindowClosingCommandClass : IWindowClosingCommand
    {
        #region структуры и классы
        #endregion
        #region переменные
        /// <summary>объект модель-представления private</summary>
        private IViewModel viewModel;
        /// <summary>объект модель-представления public</summary>
        public IViewModel ViewModel { get { return viewModel; } }
        /// <summary>событие, происходящее при возникновении изменений, влияющих на то, должна ли выполняться данная команда</summary>
        public event EventHandler CanExecuteChanged;
        #endregion
        #region функции
        /// <summary>конструктор класса WindowClosingCommandClass</summary>
        /// <param name="_view_model">объект модели-представления</param>
        public WindowClosingCommandClass(IViewModel _view_model)
        {
                viewModel = _view_model;
                CanExecuteChanged = delegate { };
        }
        /// <summary>проверка на то, что команда может быть выполнена</summary>
        public bool CanExecute(object parameter)
        {
                Boolean result = false;
                //if (closeProp == 0)
                //{
                if (System.Windows.Forms.MessageBox.Show("Вы уверены, что хотите закрыть окно?", "Предупреждение", System.Windows.Forms.MessageBoxButtons.OKCancel, System.Windows.Forms.MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.OK)
                    {
                        result = true;
                    }
                    else { result = false; }
                //}
                return result;
        }
        /// <summary>выполнить команду</summary>
        public void Execute(object parameter)
        {
                ...
        }
        #endregion        
    }

19.01.2018 указатель
 
как записать в буфер этемента листа ?
public class ddata {
public ddata() {
len = 0;
}
public Socket scket;
public byte[] bufer = new byte[1024];
public int len;
}
public static List<ddata> list = new List<ddata>();

UTF8Encoding.UTF8.GetBytes("=NOOP=").CopyTo(list[i].bufer, 6);//незаписывается в буфер

18.01.2018 Дебажить .net core под linux
 
Здравствуйте,
как можно дебажить .net core приложения под линуксом.
-- дебажить со студии под виндой по ssh не вариант — т.к. надо ставить винду.
-- вс коде не подходит, т.к. оно не работает.
Нужен инструмент, похожий на gdb для c language, только что бы можно было смотреть значения для C# переменных, а не только регистры и память.

16.01.2018 Как реализовать команду для Window в wpf?
 
Приветствую.

Простой пример. Форма wpf, реализованная в MVVM(е). При загрузке формы нужно выполнить команду. Видел, как в других ситуациях можно воспользоваться библиотекой System.Windows.Interactivity. Этот же механизм пытаюсь применить здесь, но команда с событием не связывается, метод LoadWindow не вызывается. Помогите, пожалуйста, разобраться. Можно ли тут так задавать команду? Что я делаю не так? Возможно, можно задать её как-то по-другому? Буду очень благодарен за совет.
<Window x:Class="ClassLibrary1.ViewWindow4.ViewWindowClass4"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             MinHeight="100"
             MinWidth="100"
             Height="Auto"
             Width="100"
             SizeToContent="WidthAndHeight"
             WindowStartupLocation="CenterScreen"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding Path=WWindowLoadedCommand, Mode=TwoWay}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
    </Grid>
</Window>

namespace ClassLibrary1.ViewModelLib4
{
    public class ViewModelClass4 : Notifier, IViewModel4
    {
        ModelClass4 model;
        private ICommand wWindowLoadedCommand;
        public ICommand WWindowLoadedCommand { get { return wWindowLoadedCommand; } set { wWindowLoadedCommand = value; NotifyPropertyChanged("WWindowLoadedCommand"); } }
        public ViewModelClass4(ModelClass4 _model)
        {
            model = _model;

            WWindowLoadedCommand = new WindowLoadedCommandClass(this);
        }
        public void LoadWindow()
        {
        }
    }
    /// <summary>класс-нотификатор для привязки к полям форм</summary>
    public class Notifier : INotifyPropertyChanged
    {
        #region структуры и классы
        #endregion
        #region переименные
        /// <summary>событие изменения значения поля в форме</summary>
        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        #endregion
        #region функции
        /// <summary>функция-обработчик события изменения значения поля в форме</summary><param name=""></param>
        protected void NotifyPropertyChanged(
            string propertyName)
        {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
}

namespace ClassLibrary1.CommandLib4
{
    /// <summary>команда загрузки окна</summary>
    public class WindowLoadedCommandClass : IWindowLoadedCommand4
    {
        #region структуры и классы
        #endregion
        #region переменные
        /// <summary>объект модель-представления private</summary>
        private IViewModel4 viewModel;
        /// <summary>объект модель-представления public</summary>
        public IViewModel4 ViewModel
        {
            get { return viewModel; }
        }
        /// <summary>событие, происходящее при возникновении изменений, влияющих на то, должна ли выполняться данная команда</summary>
        public event EventHandler CanExecuteChanged = delegate { };
        #endregion
        #region функции
        /// <summary>конструктор класса SelectionActionChangedCommandClass</summary>
        /// <param name="_view_model">объект модели</param>
        public WindowLoadedCommandClass(IViewModel4 _view_model)
        {
                viewModel = _view_model;
        }
        /// <summary></summary>
        public bool CanExecute(object parameter)
        {
                return true;
        }
        /// <summary></summary>
        public void Execute(object parameter)
        {
                viewModel.LoadWindow();
        }
        #endregion
    }
}

14.01.2018 Встроенная в ASP.NET Identity уязвимость
 
Разбираюсь тут с asp.net core
Как известно, в ASP.NET можно использовать встроенную систему авторизации — Identity, можно обойтись и без нее, используя авторизацию на базе Cookies и самому реализовать всю логику Identity.
Но и в том и в том случае кроется подвох — имеется серьезная уязвимость, думаю она не особо критична для серьезных разработчиков, но в любом случае, надо понимать что происходит, чтобы найти способ ее устранить.

В общем, суть такая, что для авторизации при входе на сайт, достаточно просто иметь сохраненные куки. Это конечно, логично и все так делают.
Но в этих куках никак не учитывается пароль, и соотвественно, middleware аутентификации не проверяет соотвствеие пароля хешу в БД. Она просто дешифрует куки в которых содержится логин и все права пользователя на сайте.

А значит, если некий Вася залез на сайт с компа Коли, потом пришел домой, вспомнил что сохранил там пароль, и потому решил его сменить, то... Коля тем не менее сможет войти на сайт под учеткой Васи.

Возможно, эта проблема не только ASP.NET, но и более общая.
Кто как с ней борется?

11.01.2018 неблокирующие сокеты
 
есть Select но как им пользоваться примеров в сети нет
да и неудобно подтверждение и чтение в одном списке в C++ было удобнее ...
помогите примерами или чем сможете (не путайте с асинхронными)
зарание спасибо!

11.01.2018 Как сделать wpf-binding контрола в Grid другого контрола?
 
Приветствую.

Для простоты сформулирую сферическую задачу в вакууме. Пусть есть 2 различных wpf-контрола и одно окно с гридом, призванное отображать в себе один из контролов. Каждая форма в отдельности спроектирована по паттерну MVVM (видно по пространствам имён ниже). Пусть контролы выглядят так:
<UserControl ...>
    <Grid>
        <Label Content="It is my massage1111111111" HorizontalAlignment="Left"  Margin="77,115,0,0" VerticalAlignment="Top"/>
    </Grid>
</UserControl>

<UserControl ...>
    <Grid>
        <Label Content="It is my massage2222222222" HorizontalAlignment="Left"  Margin="77,115,0,0" VerticalAlignment="Top"/>
    </Grid>
</UserControl>

Отобразить их в окне формы можно разными способами. Один из них такой (нужный контрол раскомментировать):
<Window ...
             xmlns:form1="clr-namespace:ClassLibrary1.Form1.ViewControl"
             xmlns:form2="clr-namespace:ClassLibrary1.Form2.ViewControl">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid x:Name="gMyGrid" Grid.Row="0" Grid.Column="0">
                <!--<form1:ViewControlClass Grid.Row="0" Grid.Column="0"/>-->
                <!--<form2:ViewControlClass Grid.Row="0" Grid.Column="0"/>-->
        </Grid>
    </Grid>
</Window>

Но мне хотелось бы сделать это другим способом: передавать эти контролы в виде некоей привязываемой переменной (назовём её, например, MyControl). Как-то примерно так чтобы это выглядело:
<Window ...>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid x:Name="gMyGrid" Grid.Row="0" Grid.Column="0" DataContext = "{Binding Path=MyControl}/>
    </Grid>
</Window>

Подскажите, пожалуйста, как правильно привязать переменную и какой у неё должен быть при этом тип с коде C#? Пробовал объявлять её как-то так во ViewModelClass для третьей формы (которая Window), но этот вариант не работает:
        private ClassLibrary1.Form1.ViewModelLib.ViewModelClass myControl;  
        public ClassLibrary1.Form1.ViewModelLib.ViewModelClass MyControl
        { 
            get { return myControl; } 
            set { gMyGridControl = value; NotifyPropertyChanged("myControl"); } 
        }

Буду благодарен за совет.

05.01.2018 [IIS,network] Задержка вызова
 
Приветствую комрады.
Досталась мне тут на НГ задача от клиента
Максимально упрощу. Есть https страница, на ней по действиям человека делаются запросы к нам в систему (POST). Сервер Win2012r2, WCF приложение под IIS'ом.
Иногда у клиентов происходит долгий вызов к нам, и выглядит это как большая задержка в реакции, до десятков секунд. В самом WCF приложении вызов обрабатывается за единицы миллисекунд. Пинг до сервера небольшой 100-200мс, клиенты в штатах, сам сервак(выделенный, 8 ядер, 96 гигов озу, чисто под нас) в германии в датацентре. Куда уходит время непонятно.

С чего начать? Свои методы отпрофилировали, выполняются быстро, задержек нет. Грешу на IIS, на нем крутится несколько приложений, но всем выставлены ограничения по использованию CPU, либо сеть.

Вот так выглядит har лог с клиента.
http://files.rsdn.org/57104/delay.png

29.12.2017 [ANN] Виртуализация CIL
 
Потихоньку пишем виртуализацию CIL. Пример того что было и что стало можно скачать здесь.

28.12.2017 Как закешировать WSDL?
 
Всем привет!

Есть работающие WCF-сервисы
С них клиенты почти перед каждым перед запросом запрашивают WSDL (прошу углубляться в тему "зачем")
Есть мнение, что запрос WSDL каждый раз ее генерит, чем нагружает сервисы
Вопрос — можно ли однократно полученную WSDL как-то положить в кеш и при ее запросе отправлять содержимое кеша?
Спасибо...

PS. WSDL запрашивается по другому порту и биндингу, нежели все остальное
Какой лучше тип биндинга (с точки зрения минимализации ресурсоемкости) для такого запроса использовать?

27.12.2017 .net core OutDir
 
Здравствуйте, столкнулся с следующей проблемой.

При сборке проекта к пути добавляет артефакт в виде "netstandard2.0"
т.е не в ProjectPath\bin\Debug , а в ProjectPath\bin\Debug\netstandard2.0\

Погуглив, я обноружил,что рекомендуют добавить в PropertyGroup
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>


Часть проектов угомонилисьи начали воспринимать эту настройку, хотя и создавали пустую папку "netstandard2.0",
но писали как я и хотел, в ProjectPath\bin\Debug.

Кроме одного засланца,не могу понять где проблема зарыта
вот csproj проекта, который отказывается напрочь писать в bin\Debug.

связный проекты Kom.Domain, Kom.IBL, Kom.IDAL пишутся в bin\Debug как я и ожидал
но основной Kom.BL создает себе директорию netstandard2.0

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
  <PropertyGroup Label="Globals">
    <SccProjectName>SAK</SccProjectName>
    <SccProvider>SAK</SccProvider>
    <SccAuxPath>SAK</SccAuxPath>
    <SccLocalPath>SAK</SccLocalPath>
  </PropertyGroup>
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>    
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <PlatformTarget>x64</PlatformTarget>
    <OutputPath>bin\Debug</OutputPath>
    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
    <AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>

  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Autofac" Version="4.6.2" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
    <PackageReference Include="Microsoft.Extensions.Options" Version="2.0.0" />
    <PackageReference Include="Microsoft.NET.Sdk" Version="1.0.0-alpha-20161104-2" />
    <PackageReference Include="NETStandard.Library" Version="2.0.1" />
    <PackageReference Include="Newtonsoft.Json" Version="9.0.2-beta1" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\Kom.Domain\Kom.Domain.csproj" />
    <ProjectReference Include="..\Kom.IBL\Kom.IBL.csproj" />
    <ProjectReference Include="..\Kom.IDAL\Kom.IDAL.csproj" />
  </ItemGroup>
  
</Project>

26.12.2017 Как создать новый процесс?
 
Как создать управляемый (managed) процесс не имея exe-шника?
Т.е. чтобы не указывать в Process.Start или его параметрах какой-то выполняемый файл с диска.

Это мне нужно для того, чтобы у того процесса была своя куча. Создам в нём объект, сконнекчусь с ним и через него буду пользоваться.
А когда перестану — процесс завершится и вся его куча разом убъётся.

26.12.2017 Контексты
 
Если бы была возможность создавать отдельные кучи для контекстов
Автор(ы): Тимофей Казаков
Дата: 20.12.2003
Контексты не являются чем-то принципиально новым. однако нельзя сказать, что их использование широко распространено. Статья показывает, что может дать разработчику использование этой технологии.
— это было бы хорошо или плохо? Если плохо, то чем?

19.12.2017 Как правильно передать объект из C# в библиотеку C++?
 
Приветствую.

Есть библиотека на C++. Есть программа на C#, которая её использует.

В качестве параметров библиотека принимает "структуру из структуры из ссылок на функции":
    public enum CallbackResult
    {
        OPERATION_OK,
        OPERATION_ERR
    }
    public class LibraryMediatorClass
    {
        #region структуры и классы
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct LibraryInitialContext
        {
            //[MarshalAs(UnmanagedType.LPStruct)]
            public SetOfCallbacks callbacks;
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct SetOfCallbacks
        {
            //[MarshalAs(UnmanagedType.LPStruct)]
            public SendAPDU sendAPDU;
        };
        #endregion
        #region переменные
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate CallbackResult SendAPDU([MarshalAs(UnmanagedType.LPStr)] String apdu, ulong apduLength, [MarshalAs(UnmanagedType.LPStr)] String response, ulong maxResponseLength, [MarshalAs(UnmanagedType.U8)] UInt64 responseLength);
        [DllImport(@"com_ftc_library_lib_s.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "initializeLibrary", CallingConvention = CallingConvention.Cdecl)]
        private static extern int initializeLibrary([In]LibraryInitialContext context);
        #endregion
        #region функции
        public LibraryMediatorClass()
        {
                SetOfCallbacks soc = new SetOfCallbacks();

                soc.sendAPDU = new SendAPDU(_SendAPDU);

                LibraryInitialContext libraryInitialContext = new LibraryInitialContext();
                libraryInitialContext.callbacks = soc;
                int qwe = initializeLibrary(libraryInitialContext);
        }
        public static CallbackResult _SendAPDU([MarshalAs(UnmanagedType.LPStr)] String apdu, ulong apduLength, [MarshalAs(UnmanagedType.LPStr)] String response, ulong maxResponseLength, [MarshalAs(UnmanagedType.U8)] UInt64 responseLength)
        {
            return CallbackResult.OPERATION_OK;
        }
        #endregion
    }

После запуска функция initializeLibrary возвращает Exception типа "Попытка чтения или записи в защищенную память..." Предпологаю, что неправильно объявляю структуры/классы внутри структур, которые передаются в библиотеку (закомментированные атрибуты)? Подскажите, пожалуйста, как передавать подобные данные в библиотеку С++? Что я делаю не так?

Спасибо большое!

18.12.2017 Real Life ComparerBuilder
 
Залил в github свой старый сабж

Кроме отсутствия Emit есть ещё две вишенки на торте:
1. Опция "Null идут раньше/позже не-наллов?"
2. больше кастомизации. В примере ниже впереди идут доктора, причем сначала 42-летние, потом все остальные отсортированные по имени, тайтлу и возрасту.

Пример
public class Demo
{
    class Person
    {
        public string Title;
        public string Name;
        public int? Age;
    }

    public static void Test()
    {
        StringComparer ignoreCase = StringComparer.InvariantCultureIgnoreCase;
        string highlightTitle = "Dr.";
        int highlightAge = 42;

        IComparer<Person> comparer = new ComparerBuilder<Person>()
            .Compare(x => ignoreCase.Equals(highlightTitle, x.Title))
            .Compare(x => x.Age.HasValue && highlightAge == x.Age.Value)
            .CompareString(x => x.Name, ignoreCase)
            .CompareString(x => x.Title, ignoreCase)
            .Compare(x => x.Age, OrderFlavour.Backward | OrderFlavour.NullGoesFinally)
            .GetComparer();

        Enumerable.Empty<Person>().ToList().Sort(comparer);
        Enumerable.Empty<Person>().OrderBy(x => x, comparer).ToList();
    }
}


Сам ComparerBuilder.cs (около 100 строчек кода)
Понятно что если сортировать ValueTypes то будут короткоживущие боксинги. Другие косяки есть?


P.S. Кстати, а почему в Enumerable нет
IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, IComparer<TSource> comparer)

15.12.2017 Передача делегата в библиотеку C++ в качестве параметра
 
Добрый день.

Работаю с C#.

Есть стандартная библиотека microsoft pinvokelib.dll, написанная на C++:

https://msdn.microsoft.com/ru-ru/library/as6wyhwt.aspx

Я нашёл её реализацию в интернете:

http://files.rsdn.org/82761/pinvokelib.dll

Среди прочего она содержит примеры функций, которые принимают в качестве аргументов ссылки на функции. Пример реализации вызова таких функций из C# также есть в MSDN:

https://msdn.microsoft.com/ru-ru/library/5zwkzwf4.aspx

Я реализовал выше описанный пример у себя. На 2-х разных версиях Студии (2012 и 2015). В обоих случаях возникает СОБЫТИЕ (НЕ ИСКЛЮЧЕНИЕ):

"Обнаружено событие PinvokeStackImbalance"
Вызов функции PInvoke "ConsoleApplication5!ConsoleApplication5.Program::TestCallBack" разбалансировал стек. Вероятно, это вызвано тем, что управляемая сигнатура PInvoke не совпадает с неуправляемой целевой сигнатурой. Убедитесь, что соглашение о вызовах и параметры сигнатуры PInvoke совпадают с неуправляемой целевой сигнатурой.

Переданные функции успешно вызываются и передают корректные результаты в библиотеку. Т.к. это не исключение, то программа не прерывается и, вроде как, полностью и в данном случае корректно выполняется.

Чтобы избежать данного сообщения, я попробовал добавить некоторые атрибуты для данного кода в C#:
    public class App
    {
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.U1)]
        public delegate bool FPtr([MarshalAs(UnmanagedType.I4)] Int32 value);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.U1)]
        public delegate bool FPtr2([MarshalAs(UnmanagedType.LPStr)] string value);

        // Declares managed prototypes for unmanaged functions.
        //[DllImport("..\\LIB\\PinvokeLib.dll")]
        [DllImport("PinvokeLib.dll")]
        public static extern void TestCallBack(FPtr cb, [MarshalAs(UnmanagedType.I4)] Int32 value);
        //public static extern void TestCallBack(IntPtr cb, [MarshalAs(UnmanagedType.I4)] Int32 value);
        //[DllImport("..\\LIB\\PinvokeLib.dll")]
        [DllImport("PinvokeLib.dll")]
        public static extern void TestCallBack2(FPtr2 cb2, [MarshalAs(UnmanagedType.LPStr)] String value);
        //public static extern void TestCallBack2(IntPtr cb2, [MarshalAs(UnmanagedType.LPStr)] String value);

        public static void Main()
        {
            FPtr cb = new FPtr(App.DoSomething);
            //LibWrap.TestCallBack(cb, 99);
            TestCallBack(cb, 99);
            //TestCallBack(Marshal.GetFunctionPointerForDelegate(cb), 99);
            FPtr2 cb2 = new FPtr2(App.DoSomething2);
            //LibWrap.TestCallBack2(cb2, "abc");
            TestCallBack2(cb2, "abc");
            //TestCallBack2(Marshal.GetFunctionPointerForDelegate(cb2), "abc");

            Console.ReadLine();
        }
        [return: MarshalAs(UnmanagedType.U1)]
        public static bool DoSomething([MarshalAs(UnmanagedType.I4)] Int32 value)
        //public static bool DoSomething(int value)
        {
            Console.WriteLine("\nCallback called with param: {0}", value);
            // ...
            return true;
        }
        [return: MarshalAs(UnmanagedType.U1)]
        public static bool DoSomething2([MarshalAs(UnmanagedType.LPStr)] String value)
        //public static bool DoSomething2(String value)
        {
            Console.WriteLine("\nCallback called with param: {0}", value);
            // ...
            return true;
        }
    }


При этом после обращения и выполнения функции DoSomething функция TestCallBack выдаёт исключение:

AccessViolationException was unhandled
An unhandled exception of type 'System.AccessViolationException' occurred in ConsoleApplication1.exe
Additional information: Попытка чтения или записи в защищенную память. Это часто свидетельствует о том, что другая память повреждена.

Что я делаю не так? Как корректно вызвать данные функции, чтобы не было ни сообщений, ни исключений??

14.12.2017 .net core 2.0 GetType возвращает null
 
Привет!

У меня возникла проблема при работе с модулями в autofac.
Он не мог определить зарезолвить
System.Type.GetType("Union.BL.Common.Autofac, Union.BL")

следовательно не смог подтянуть конфиг КонтейнерБилдера для слоя BL.

фиксится тем что добавляю к верхнему слою ссылки на все проекты, тогда
выше указаный код отрабатывает и автофак работает как часы.

но какой профит? смысл развязать зависимости, почему в обычном .net работает
System.Type.GetType("Union.BL.Common.Autofac, Union.BL")

если сборка Union.BL лежит под проектом, а в .net core это сделано через зад.

кто сталкивался с такой проблемой ?
спасибо)

14.12.2017 туториалов про GPU на C# под линукс! Почему так мало?
 
Вот я, типичный студент, нужно мне посчитать PageRank для одного поискового запроса на текстовой базе, как мне это сделать на C#?

1) я открываю github и ищу "метод гаусса" — находится три тысячи репозиториев на всех языках, 74 на C# (вот маньяки — чужой код не читаем, всегда пишем свой)
2) мне не нужен итеративный способ посчёта, так как поисковый запрос у меня конкретный, то страниц он затрагивает мало, я хочу посчитать сразу точно, зачем мне итерации?
3) есть ускоренное умножение, которые быстрее (ассимптотическая сложность меньше), ну сложно было библиотеку один раз сделать?

Что делать?

 
 
 
 
10.12  .NET Reactor
15.11  n
15.11  C# ClickOnce