» Разработка > Кроссплатформенное использование классов .Net из неуправляемого кода. Или аналог IDispatch на Linux
» Разработка > Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux
» Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux II
» Асинхронное программирование в 1С через .Net Native ВК
1С, Linux, Excel, Word, OpenXML,ADO и Net Core
На данный момент в .Net Core 2 варианта динамической компиляции
1. Это аналог CodeDom Microsoft.CodeAnalysis.CSharp.CSharpCompilation
2. Roslyn Scripting Api. Примеры здесь
var compilation = Microsoft.CodeAnalysis.CSharp.CSharpCompilation.Create("a")
.WithOptions(new Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions(Microsoft.CodeAnalysis.OutputKind.DynamicallyLinkedLibrary))
.AddReferences(
Microsoft.CodeAnalysis.MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location))
.AddSyntaxTrees(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(
@"
using System;
public class C
{
public C(){}
public string M()
{
return ""Hello Roslyn."";
}
}"));
var fileName = @"d:\NetStandart\TestCoreNetApp\src\TestCoreNetApp\bin\Debug\netcoreapp1.0\a.dll";
compilation.Emit(fileName);
var a = System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromAssemblyPath(fileName);
Type тип = a.GetType("C");
var obj = Activator.CreateInstance(тип);
var res = тип.GetMethod("M").Invoke(obj, null);
Console.WriteLine(res.ToString());
Этот подход хорош когда нужно обновить библиотеку. Но при этом создается DLL со всеми вытекающими.
Второй способ мне нравится больше. Возьмем на примере получения делегата.
string words = "надо заменить все первые буквы в словах на заглавные";
string pattern = @"\w+";
var scr = Microsoft.CodeAnalysis.Scripting.ScriptOptions.Default;
var mscorlib = Assembly.Load(System.Runtime.Loader.AssemblyLoadContext.GetAssemblyName(@"c:\Users\Smirnov_SA\.nuget\packages\Microsoft.NETCore.Portable.Compatibility\1.0.1\ref\netcore50\mscorlib.dll"));
scr =scr.WithReferences(mscorlib, typeof(MulticastDelegate).GetTypeInfo().Assembly, typeof(System.Runtime.CompilerServices.IStrongBox).GetTypeInfo().Assembly, typeof(MatchEvaluator).GetTypeInfo().Assembly, typeof(Regex).GetTypeInfo().Assembly)
.WithImports("System", "System.Text.RegularExpressions");
string КодДелегата = @"return (MatchEvaluator)((match) =>
{
string x = match.Value;
// If the first char is lower case...
if (char.IsLower(x[0]))
{
// Capitalize it.
return char.ToUpper(x[0]) + x.Substring(1, x.Length - 1);
}
return x;
});";
var result = Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.EvaluateAsync(КодДелегата, scr).Result;
MatchEvaluator evaluator = (MatchEvaluator)result;
Console.WriteLine(Regex.Replace(words, pattern, evaluator));
Обязательно нужно указать ссылки на:
mscorlib.dll
System.Private.CoreLib.ni.dll
System.Runtime.dll
Для компиляции используются следующие библиотеки:
«Microsoft.CodeAnalysis.CSharp»: «2.0.0-beta3»,
«Microsoft.CodeAnalysis.CSharp.Scripting»: «2.0.0-beta3»,
«Microsoft.CodeAnalysis.Scripting.Common»: «2.0.0-beta3»,
Microsoft.CodeAnalysis.Scripting
По динамической компиляции. В свое время работал с запчастями для автомобилей. А там куча поставщиков и клиентов. При этом прайсы на миллионы позиций. И каждый горазд давать данные в своем формате. Было проще для каждого клиента создавать код записывать в справочник и использовать через Выполнить или Вычислить. Правда при работе с миллионными прайсами этот подход тормозил.
Так или иначе приходилось писать DLL и работать через COM.
C помощью динамической компиляции можно хранить текст кода и применять его в зависимости от условий. В том числе динамически формировать по условиям, а скомпилированный делегат можно кэшировать для повторного использования.
Скорость компиляции достаточно высокая (кроме первого раза секунд 5).
Перейдем к 1С. Так воторй алгоритм на 1С выглядит так
стр = "return (MatchEvaluator)((match) =>
|{
| string x = match.Value;
|// If the first char is lower case...
|if (char.IsLower(x[0]))
|{
|// Capitalize it.
|return char.ToUpper(x[0]) + x.Substring(1, x.Length - 1);
|}
|return x;
|
|});";
текст = "надо заменить все первые буквы в словах на заглавные";
Образец = "\w+";
// MatchEvaluator evaluator = (MatchEvaluator)ПолучитьДелегат();
ScriptOptions=ъТип("Microsoft.CodeAnalysis.Scripting.ScriptOptions","Microsoft.CodeAnalysis.Scripting");
CSharpScript=ъТип("Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript","Microsoft.CodeAnalysis.CSharp.Scripting");
scr = ъ(ScriptOptions.Default);
mscorlibСборка = ъ(Врап.Сборка("mscorlib.dll",Истина));
Private_CoreLibСборка=ъ(Врап.Сборка("System.Private.CoreLib.ni",Истина));
System_RuntimeСборка=ъ(Врап.Сборка("System.Runtime",Истина));
RegularExpressionsСборка=ъ(Врап.Сборка("System.Text.RegularExpressions",Истина));
Regex=ъ(RegularExpressionsСборка.GetType("System.Text.RegularExpressions.Regex"));
scr =ъ(scr.WithReferences(mscorlibСборка.ПолучитьСсылку(), Private_CoreLibСборка.ПолучитьСсылку(), System_RuntimeСборка.ПолучитьСсылку(), RegularExpressionsСборка.ПолучитьСсылку()));
scr =ъ(scr.WithImports("System", "System.Text.RegularExpressions"));
evaluator = ъ(ъ(CSharpScript.EvaluateAsync(стр, scr.ПолучитьСсылку())).Result);
Сообщить(Regex.Replace(текст, Образец, evaluator.ПолучитьСсылку()));
В общем ничего особенного. Получили сборки, дали ссылки на них скомпилировали, вызвали.
Перейдем к более сложным примерам. Так в предыдущей статье я показывал примеры использования DocumentFormat.OpenXml на примере чтения Excel и Word.
Там была проблема в скорости из-за приведения строки к объекту через функцию ъ и сама скорость вызова из 1С в 5 раз медленнее её родного кода.
Поэтому вынесем большую часть кода в .Net. Аналогичный вариант есть на большом .Net
.Net в 1С. На примере использования HTTPClient,AngleSharp. Удобный парсинг сайтов с помощью библиотеки AngleSharp, в том числе с авторизацией аля JQuery с использованием CSS селекторов. Динамическая компиляция (пример в конце статьи).
Создадим класс и скопируем его в макет. Суть класса прочитать данные ячеек и сгруппировать их по номеру строки.
public class ДанныеЯчейки
{
public string ИмяЯчейки;
public string ИмяКолонки;
public int НомСтроки;
public string ЗначениеЯчейки;
}
public class ExcelReader
{
static Regex ШаблонКолонки = new Regex("[A-Za-z]+");
OpenXmlElementList ОбщиеСтроки;
void ЗаписатьДанныеАдреса(string адрес, ДанныеЯчейки данныеЯчейки)
{
данныеЯчейки.ИмяЯчейки = адрес;
var match = ШаблонКолонки.Match(адрес);
var ИмяКолонки = match.Value;
var НомерСтроки = int.Parse(адрес.Substring(ИмяКолонки.Length));
данныеЯчейки.ИмяКолонки = ИмяКолонки;
данныеЯчейки.НомСтроки = НомерСтроки;
}
void ДобавитьДанныеОбЯчейке(List<ДанныеЯчейки> ДанныеЭселя, Cell cell)
{
var адрес = cell.CellReference.InnerText;
var text = cell.CellValue?.Text;
var DataType = cell.DataType;
string res = text;
if (DataType != null && DataType == CellValues.SharedString)
{
int ssid = int.Parse(text);
res = ОбщиеСтроки[ssid].InnerText;
}
if (res == null) return;
var result = new ДанныеЯчейки();
ЗаписатьДанныеАдреса(адрес, result);
result.ЗначениеЯчейки = res;
ДанныеЭселя.Add(result);
}
public List<ДанныеЯчейки> ReadExcel(string fileName)
{
List<ДанныеЯчейки> ДанныеЭселя = new List<ДанныеЯчейки>();
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fs, false))
{
var workbookPart = doc.WorkbookPart;
// Строки хранятся отдельно
// В ячейках хранится индекс
var pt = workbookPart.GetPartsOfType<SharedStringTablePart>();
var sstpart = pt.First();
var sst = sstpart.SharedStringTable;
ОбщиеСтроки = sst.ChildElements;
var workbook = workbookPart.Workbook;
// Получим список страниц
var sheet = workbook.Descendants<Sheet>().First();
var worksheetPart = (DocumentFormat.OpenXml.Packaging.WorksheetPart)workbookPart.GetPartById(sheet.Id);
var worksheet = worksheetPart.Worksheet;
var cells = worksheet.Descendants<Cell>();
// One way: go through each cell in the sheet
foreach (Cell cell in cells)
{
ДобавитьДанныеОбЯчейке(ДанныеЭселя, cell);
}
}
}
return ДанныеЭселя;
}
static string НайтиИмяПоследнейКолонки(List<ДанныеЯчейки> Тз)
{
var рез = "";
var ДлинаРез = 0;
foreach (var стрТз in Тз)
{
var Стр = стрТз.ИмяКолонки;
var СтрДл = Стр.Length;
if (СтрДл > ДлинаРез)
{
ДлинаРез = СтрДл;
рез = Стр;
}
else if (СтрДл == ДлинаРез && string.Compare(Стр, рез, true) > 0)
рез = Стр;
}
return рез;
}
public static object ПолучитьДанныеЭкселя(string fileName)
{
var res = new ExcelReader();
var Данные = res.ReadExcel(fileName);
var данныеЭкселя = Данные.GroupBy(ё => ё.НомСтроки).Select(ъ => new { НомСтроки = ъ.Key, Ячейки = ъ.ToArray() }).OrderBy(ь => ь.НомСтроки);
var ИмяПоследнейКолонки = НайтиИмяПоследнейКолонки(Данные);
return new { ДанныеЁкселя = данныеЭкселя.ToList(), ИмяПоследнейКолонки = ИмяПоследнейКолонки };
}
}
return new Func<string, object>(ExcelReader.ПолучитьДанныеЭкселя);
Мы описали класс чтения и возвращаем ссылку на делегат принимающий путь к файлу и возвращающий анонимный класс. Все равно в 1С мы будем работать с ним через рефлексию. Обратите внимание, что здесь описаны 2 класса.
Теперь вызовем этот код из 1С.
ScriptOptions=ъТип("Microsoft.CodeAnalysis.Scripting.ScriptOptions","Microsoft.CodeAnalysis.Scripting");
CSharpScript=ъТип("Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript","Microsoft.CodeAnalysis.CSharp.Scripting");
scr = ъ(ScriptOptions.Default);
mscorlibСборка = ъ(Врап.Сборка("mscorlib.dll",Истина));
Private_CoreLibСборка=ъ(Врап.Сборка("System.Private.CoreLib.ni",Истина));
System_RuntimeСборка=ъ(Врап.Сборка("System.Runtime",Истина));
RegularExpressionsСборка=ъ(Врап.Сборка("System.Text.RegularExpressions",Истина));
OpenXmlСбока=ъ(Врап.Сборка("DocumentFormat.OpenXml.dll"));
LinqСбока=ъ(Врап.Сборка("System.Linq", истина));
FileSystemСбока=ъ(Врап.Сборка("System.IO.FileSystem", истина));
Regex=ъ(RegularExpressionsСборка.GetType("System.Text.RegularExpressions.Regex"));
scr =ъ(scr.WithReferences(mscorlibСборка.ПолучитьСсылку(), Private_CoreLibСборка.ПолучитьСсылку(), System_RuntimeСборка.ПолучитьСсылку(), RegularExpressionsСборка.ПолучитьСсылку(),OpenXmlСбока.ПолучитьСсылку(),LinqСбока.ПолучитьСсылку(),FileSystemСбока.ПолучитьСсылку()));
scr =ъ(scr.WithImports("System", "System.Collections.Generic", "System.Linq", "System.IO", "DocumentFormat.OpenXml", "DocumentFormat.OpenXml.Packaging", "DocumentFormat.OpenXml.Spreadsheet", "System.Text.RegularExpressions"));
Текст=ПолучитьМакет("ТекстКлассаЧтенияЕксель").ПолучитьТекст();
Делегат = ъ(ъ(CSharpScript.EvaluateAsync(Текст, scr.ПолучитьСсылку())).Result);
Данные= ъ(Делегат.DynamicInvoke(ИмяФайла));
Сообщить(Данные.ИмяПоследнейКолонки);
рез=новый ТаблицаЗначений;
ПоследняяКолонка=Данные.ИмяПоследнейКолонки;
СоздатьКолонки(рез.Колонки,ПоследняяКолонка);
Колонки=рез.Колонки;
Тз=ъ(Данные.ДанныеЁкселя);
Тз=ъ(Врап.ПолучитьЭнумератор(Тз.ПолучитьСсылку()));
сч=1;
// Получили сгруппированные данные по строкам
Пока Тз.MoveNext() Цикл
стрТз= ъ(Тз.Current);
НомСтроки=стрТз.НомСтроки;
Пока сч<НомСтроки Цикл
сч=сч+1;
рез.Добавить();
КонецЦикла;
сч=сч+1;
стр=рез.Добавить();
// получим ячейки по строке
ТзГр=ъ(стрТз.Ячейки);
ТзГр=ъ(Врап.ПолучитьЭнумератор(ТзГр.ПолучитьСсылку()));
Пока ТзГр.MoveNext() Цикл
стрТзГр= ъ(ТзГр.Current);
ИмяКолонки=стрТзГр.ИмяКолонки;
ЗначениеЯчейки=стрТзГр.ЗначениеЯчейки;
// Можно конечно получить индекс зная смещение символа 64 относительно 1 и 26 разрядную систему
// но найдем колонку по имени и её индекс
Колонка=Колонки.Найти(ИмяКолонки);
стр.Установить(Колонки.Индекс(Колонка),ЗначениеЯчейки);
КонецЦикла;
КонецЦикла;
Теперь скорость обработки Экселя значительно увеличилась, а затраты на компиляцию соизмеримы с затратами на чтения файлов.
Посмотрим процесс чтения Word. Не мудрствуя лукаво я взял готовый класс здесь. Тем более там все на англицком.
// Исходники можно скачать здесь
//https://code.msdn.microsoft.com/office/CSOpenXmlGetPlainText-554918c3/sourcecode?fileId=71592&pathId=851860130
public class GetWordPlainText : IDisposable
{
// Specify whether the instance is disposed.
private bool disposed = false;
// The word package
private WordprocessingDocument package = null;
/// <summary>
/// Get the file name
/// </summary>
private string FileName = string.Empty;
/// <summary>
/// Initialize the WordPlainTextManager instance
/// </summary>
/// <param name="filepath"></param>
public GetWordPlainText(string filepath)
{
this.FileName = filepath;
if (string.IsNullOrEmpty(filepath) || !File.Exists(filepath))
{
throw new Exception("The file is invalid. Please select an existing file again");
}
this.package = WordprocessingDocument.Open(filepath, true);
}
/// <summary>
/// Read Word Document
/// </summary>
/// <returns>Plain Text in document </returns>
public string ReadWordDocument()
{
StringBuilder sb = new StringBuilder();
OpenXmlElement element = package.MainDocumentPart.Document.Body;
if (element == null)
{
return string.Empty;
}
sb.Append(GetPlainText(element));
return sb.ToString();
}
/// <summary>
/// Read Plain Text in all XmlElements of word document
/// </summary>
/// <param name="element">XmlElement in document</param>
/// <returns>Plain Text in XmlElement</returns>
public string GetPlainText(OpenXmlElement element)
{
StringBuilder PlainTextInWord = new StringBuilder();
foreach (OpenXmlElement section in element.Elements())
{
switch (section.LocalName)
{
// Text
case "t":
PlainTextInWord.Append(section.InnerText);
break;
case "cr": // Carriage return
case "br": // Page break
PlainTextInWord.Append(Environment.NewLine);
break;
// Tab
case "tab":
PlainTextInWord.Append("\t");
break;
// Paragraph
case "p":
PlainTextInWord.Append(GetPlainText(section));
PlainTextInWord.AppendLine(Environment.NewLine);
break;
default:
PlainTextInWord.Append(GetPlainText(section));
break;
}
}
return PlainTextInWord.ToString();
}
#region IDisposable interface
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
// Protect from being called multiple times.
if (disposed)
{
return;
}
if (disposing)
{
// Clean up all managed resources.
if (this.package != null)
{
this.package.Dispose();
}
}
disposed = true;
}
#endregion
public static string GetText(string FileName)
{
using (var pt = new GetWordPlainText(FileName))
{
return pt.ReadWordDocument();
}
}
}
return new Func<string,string>(GetWordPlainText.GetText);
Но вернемся к Руслишу:
ScriptOptions=ъТип("Microsoft.CodeAnalysis.Scripting.ScriptOptions","Microsoft.CodeAnalysis.Scripting");
CSharpScript=ъТип("Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript","Microsoft.CodeAnalysis.CSharp.Scripting");
scr = ъ(ScriptOptions.Default);
mscorlibСборка = ъ(Врап.Сборка("mscorlib.dll",Истина));
Private_CoreLibСборка=ъ(Врап.Сборка("System.Private.CoreLib.ni",Истина));
System_RuntimeСборка=ъ(Врап.Сборка("System.Runtime",Истина));
RegularExpressionsСборка=ъ(Врап.Сборка("System.Text.RegularExpressions",Истина));
OpenXmlСбока=ъ(Врап.Сборка("DocumentFormat.OpenXml.dll"));
LinqСбока=ъ(Врап.Сборка("System.Linq", истина));
FileSystemСбока=ъ(Врап.Сборка("System.IO.FileSystem", истина));
Regex=ъ(RegularExpressionsСборка.GetType("System.Text.RegularExpressions.Regex"));
scr =ъ(scr.WithReferences(mscorlibСборка.ПолучитьСсылку(), Private_CoreLibСборка.ПолучитьСсылку(), System_RuntimeСборка.ПолучитьСсылку(),OpenXmlСбока.ПолучитьСсылку(),FileSystemСбока.ПолучитьСсылку()));
scr =ъ(scr.WithImports("System", "System.Text", "System.IO", "DocumentFormat.OpenXml", "DocumentFormat.OpenXml.Packaging"));
Текст=ПолучитьМакет("ТекстЧтенияВорд").ПолучитьТекст();
Делегат = ъ(ъ(CSharpScript.EvaluateAsync(Текст, scr.ПолучитьСсылку())).Result);
стр = Делегат.DynamicInvoke(ИмяФайла);
Текст=Новый ТекстовыйДокумент;
Текст.ДобавитьСтроку(стр);
Текст.Показать();
Основная задача указать ссылки на используемые сборки и пространство имен.
В следующей статье я сделаю динамическое создание обертки над объектами использующих события по аналогии с
.NET(C#) для 1С. Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия
Комментарии (57)
Serginio1
06.09.2016 18:01+1Это код на 1С. Для начала нужно прочитать все статьи с начала.
xGromMx
06.09.2016 18:02+1Да у вас и .net код на русском написан
Serginio1
06.09.2016 18:09А зачем отказываться от Русслиша?
Из статьи в статью только обращают на Русслиш. Что по теме понравилось, не понравилось.
Если бы ты повнимательнее почитал статью то увидел Ужас
var данныеЭкселя = Данные.GroupBy(ё => ё.НомСтроки).Select(ъ => new { НомСтроки = ъ.Key, Ячейки = ъ.ToArray() }).OrderBy(ь => ь.НомСтроки);
xGromMx
06.09.2016 18:20И это по твоему нормально выглядит?
Serginio1
06.09.2016 19:44Я не вижу разницы между
var данныеЭкселя = Данные.GroupBy(i => i.НомСтроки).Select(n=> new { НомСтроки = n.Key, Ячейки = n.ToArray() }).OrderBy(j => j.НомСтроки);
Никакой смысловой нагрузки они не несут. Так ты и не ответил, что кроме Русслиша ты увидел?
KvanTTT
06.09.2016 20:02Название переменной
i
хотя бы можно кратко произнести, в отличие отъ
.Serginio1
06.09.2016 20:49А как произносится $
KvanTTT
07.09.2016 00:06Так переменную назвать нельзя. А произносится "доллар" легче, чем "твердый знак", да и используется реже.
Serginio1
07.09.2016 00:14+1Переменную нельзя а метод JQuery и все его прекрасно используют.
А насчет легче, то старое название еръ
значительно легче. Только вот смыл произношения при программировании? Особенно когда все поголовно используют сокращения. Смысл ъ как раз в том, что его никто практически не применяет и меньше конфликтов при одинаковом названии метода.
dmpas
06.09.2016 21:18я произношу эту букву по-старому: «ер». То же самое, что «и» или «ай».
(ненене, сам я такие названия в коде не использую!)
Shtucer
07.09.2016 08:59+1Я увидел боль. Как эту кашу набирать-то…
Serginio1
07.09.2016 09:40-1Вот ты пишешь на форуме на русском, читаешь на русском. А примеры кода приводишь на английском. У тебя есть проблемы?
Кроме того есть Punto с автопереключением. Очень удобноShtucer
07.09.2016 09:44Очень точное сравнение: что код писать, что в комментарии срать (или наоборот?) Пунто свитчер, как первейший инструмент программиста, да ещё с пометкой «очень удобно», это что-то новенькое. Но я не осуждаю, нет. Я как бы ошеломлён происходящим.
Serginio1
07.09.2016 09:55Посмотри сколько у меня статей, и в комментариях одно и тоже. И главное, что суть статей то никто не обсуждает.
denis_invader
07.09.2016 10:21Потому что 90% статьи это код, а код похож на результат какого-то «генератора» для приколов. Лично я не могу этот код читать иначе как по-диагонали, смысл в нём найти очень сложно
Serginio1
07.09.2016 10:23Спасибо. Буду стараться писать, что бы затронуло. Но проблема в том, что это статьи в основном для 1С ников. Хотя по динамическая компиляции в .Net Core очень мало информации.
Shtucer
07.09.2016 09:49+1И это мы ещё не обсуждали смысловую нагрузку коротких именований. Для 'i' я могу придумать хоть какую-то смысл, это обычно первая буква от «index», или (реже) «iterator» Для ваших «ё» и «ъ» я тоже могу кое-что придумать, но это никак не относится к самой программе, тут, скорее всего, будет переход на личности.
Sing
07.09.2016 12:02Да, не несут. Именно поэтому так тоже не стоит писать. Бессмысленные названия переменных — это плохо. Для того, чтобы понять, что такое j придётся читать всю строку и осмысливать каждый метод.
Serginio1
07.09.2016 12:47А в Linq ты и так знаешь какой делегат от тебя ждут. Например
public static IEnumerable<TSource> Where<TSource>( this IEnumerable<TSource> source, Func<TSource,?bool> predicate )
Но никто не пишетWhere(ЭлементМассива =>ЭлементМассива >0)
Все сокращают, так как и так понятно, что это за переменная. И искать особый смысл в них никто не ищет.Sing
07.09.2016 13:05> Все сокращают, так как и так понятно, что это за переменная.
ЕСЛИ понятно, что это за переменная. Переменная «ё» или «ъ» не даёт никакого понятия об этом.
То есть
products.Where(p => p.Name == "Chair");
выглядит понятно, а
Данные.GroupBy(ё => ё.НомСтроки)
уже не очень.Serginio1
07.09.2016 13:37На вкус и цвет… Никакой разницы между p и ё не вижу. Там хоть смайлик ставь.
Кстати Ограниченность набора символов Unicode для идентификаторовfishca
07.09.2016 13:41Все таки лучше идентификаторам давать осмысленные имена. Это признак хорошего программерского тона.
Serginio1
07.09.2016 13:46И в чем «p» осмысленнее «ё»? Две буквы. Причем р еще можно читать и по русски
Sing
07.09.2016 15:44Осмысленные — это типа «product».
До одной буквы сокращают, когда из контекста очевидно, что за элемент мы используем.
Например, у нас есть список products, productsArray, productsList и т.п. Соответственно, один элемент этого списка — product, сокращаем до первой буквы p. Как-то так
Но я не могу придумать ни одной причины, почему список ячеек нужно сокращать до «ё». А когда идёт что-то типа «ё => ё.foo()» я читаю это как «ё моё».Serginio1
07.09.2016 16:03А можно и ёпрст или на ё бывает и за ё бывает
fishca
07.09.2016 16:28Самое главное еще иметь чувство меры и баланса и не впадать в крайности давая идентификаторы типа: «ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент», при использовании таких даже широкоформатного монитора не хватает :)
Serginio1
07.09.2016 16:36Зато понятно. Я кстати не против названия классов, особенно когда IntelliSense работает. И не нужно долго набирать или копировать.
cleaner_it
08.09.2016 14:30Я с вами согласен, в комментариях к прошлой статье об этом говорил. Большинство думает, что понятные имена — это «слишком длинно, и затрудняет чтение».
PS: А сколько раз меня выручали осмысленные наименования, когда приходится возвращаться к коду годичной давности!fishca
08.09.2016 16:39PS: А сколько раз меня выручали осмысленные наименования, когда приходится возвращаться к коду годичной давности!
Воистину так!Serginio1
08.09.2016 17:34Вот и я даю осмысленные имена. Только на русском. Я его значительно лучше понимаю англицкого
xGromMx
08.09.2016 19:28Еще раз спрошу, в чем осмысленность «ъ»?
medvedevia
08.09.2016 20:03О, а я смотрю Вы как раз на javascript программите, вот и расскажите нам в чем смысл $…
Serginio1
08.09.2016 23:10Спасибо за поддержку. А то народ не интересует вызов управляемого кода из натива.
Динамическая компиляция, рефлексия с выводом типа в дженериках и максимальная итд.
Всех волнует только Руслиш и ъ.
Serginio1
08.09.2016 23:07Еще раз отвечу. ъ позаимствован из JQuery от $
Смысл тот же. Краткость и мало конфликтность. А конструкций типа ъ(ъ(ъ( много
и на каждом шагу к сожалению этот ъ нужно использовать. Просто давать что то осмысленное типа
ПолучитьОбъект(ПолучитьОбъект(ПолучитьОбъект(Объект.ВызватьМетод(Параметр.ПолучитьСсылку())))
fishca
07.09.2016 09:31+1Вот зачем прикручивается кроссплатформенный С#, который все равно обращается к кроссплатформенному С++, если можно сразу на С++ все написать? Есть от этого какая-то выгода?
Serginio1
07.09.2016 09:37А можно на ссылочку на
который все равно обращается к кроссплатформенному С++,
Смысл в том, что можно использовать .Net сборки напрямую без дополнительного написания ВК. С С++ тебе нужно под каждую задачу делать ВК, знать С++.
Здесь ты используешь уже готовые классы, либо пишешь сборку на .Net без всяких заморочек с ВК.
То есть одна ВК через которую ты можешь использовать любые сборки. Не нужно знать C#, VB.NET,F#. Нужно знать только классы методы и свойства. Это аналог COM.fishca
07.09.2016 13:25Почему бы не написать одну ВК на С++, а не С#? Тем более платформа 1С написана на С/С++, ОС-и тоже на нем же. Будет нативное взаимодействие. Зачем использовать прослойку в виде .Net?
Serginio1
07.09.2016 13:42ВК то написана на С++ но внутри используется доступ к статическим методам .Net библиотеки. А там через рефлексию можно вызвать методы объекта и статические методы. Почитай мои первые статьи.
В C++ там не то, что рефлексии (динамический доступ к информации о методах и свойствах, но и вызов соответсвующих методов) нормальной информации о типе сложно получить.
medvedevia
07.09.2016 13:42А почему все не пишут на с/с++, если операционная система написана на с/с++? Вот и тут тоже самое…
fishca
07.09.2016 13:46Я еще могу понять использовать отличный от С/С++ язык для разработки какого-либо ПО, но вот использования виртуальных машин в виде .Net и Java я все равно до сих пор не могу понять. Явных преимуществ, сколько не пытался себя заставить, ну не вижу.
Serginio1
07.09.2016 13:52Кто тебе наплел про виртуальную машину? MSIL код компилируется в натив. Другое дело, что компилятор не оптимизирует код из-за наличия рефлексии. Сейчас есть .Net Native Компиляция приложений с помощью машинного кода .NET
Так создай мой аналог компоненты которая из 1С будет использовать любую библиотеку написанную на С++ без дополнительных телодвижений. В том числе и события.fishca
07.09.2016 16:30Так создай мой аналог компоненты которая из 1С будет использовать любую библиотеку написанную на С++ без дополнительных телодвижений. В том числе и события.
Мне это не нужно. И я ничуть не хотел принизить твоих заслуг по написанию ВК. Но мне не понятно зачем Микрософт сделало прослойку .net, а потом все равно компиляцию в нативный код.Serginio1
07.09.2016 16:42Я не про заслуги, а про возможности. Зачем прослойка?
1. Компоновка библиотек. Есть полная информация о типах и версиях.
При этом библиотеки написанные под .Net 2.0 можно использовать под 4.5
2. Независимость от процессора (AnyCPU)
3. Рефлексия. За счет которой и создана данная ВК
4. Динамическая компиляция.
xGromMx
Что делает «ъ»?
Serginio1
Так как в Native Api нельзя передавать объекты, то возвращается ссылка
xGromMx
Как вообще это читать?
yarosroman
хочется это развидеть.
wildboar47
почему нельзя было назвать это не «ъ» а «ВернутьСсылку»?
Serginio1
А почему в JQuery используют $ вместо JQuery. Просто очень много используетя в том числе и ъ(ъ(ъ
Так удобнее для восприятия
fishca
на фкус и свет у фсех фломастеры расные :D