.NET(C#) для 1С. Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия

Публикация № 417830

Разработка - Разработка внешних компонент

.Net C# event DynamicMethod

51
Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия, а так же генерация модулей на C# и 1С для подключения к событиям. Использование DynamicMethod и ILGenerator. Представлены примеры для использовании событий System.IO.FileSystemWatcher (Ожидает уведомления файловой системы об изменениях и инициирует события при изменениях каталога или файла в каталоге.) и SerialPort (обработка сканера штрих кода подключенного к COM порту). Обертка позволяет использовать классы .Net только на языке 1С. Реализация 1C Messenger описанного здесь http://infostart.ru/public/434771/

 Эта статья является дополнением разработки Использование сборок .NET в 1С 7.x b 8.x находящейся здесь //firstportal.ru/public/238584/

 

Как то раз пришлось написать интеграцию 1С с WhatsApp. А там порядка 30 событий.

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

Не поленился и написал кодогенератор.

Рассмотрим генерацию кода на примере System.IO.FileSystemWatcher

https://msdn.microsoft.com/ru-ru/library/system.io.filesystemwatcher(v=vs.110).aspx

 

using System;

using System.Runtime.InteropServices;

using System.Windows.Forms;

using System.Threading;

using System.Threading.Tasks;

 

 

[ComVisible(true)]

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]

[Guid("6821a54a-19a2-4e66-85d9-e65396958080")]

public interface IВрапперДляSystem_IO_FileSystemWatcher

{

 

    [DispId(0x00000001)]

    void ОшибкаСобытия(Stringсобытие, object value, objectисключение);

    [DispId(0x00000002)]

    void Changed(object value);

    [DispId(0x00000003)]

    void Created(object value);

    [DispId(0x00000004)]

    void Deleted(object value);

    [DispId(0x00000005)]

    void Error(object value);

    [DispId(0x00000006)]

    void Renamed(object value);

    [DispId(0x00000007)]

    void Disposed(object value);

 

}

 

 

[ComVisible(true)]

[ClassInterface(ClassInterfaceType.AutoDual)]

[Guid("c3919804-ff5f-4d2a-a773-5067a1e051e1")]

[ComSourceInterfaces(typeof(IВрапперДляSystem_IO_FileSystemWatcher))]

public class ВрапперДляSystem_IO_FileSystemWatcher

{

 

    [ComVisible(false)]

    public delegate void Событие_Delgate();

    [ComVisible(false)]

    public delegate void СобытиеСПараметром_Delgate(object value);

    [ComVisible(false)]

    public  delegate void СобытиеСПараметрами_Delgate(Stringсобытие, object value, objectисключение);

 

    public System.IO.FileSystemWatcher РеальныйОбъект;

    dynamic AutoWrap;

    private SynchronizationContext Sc;

    public event СобытиеСПараметрами_Delgate ОшибкаСобытия;

    public Exception ПоследняяОшибка;

    public event СобытиеСПараметром_Delgate Changed;

    public event СобытиеСПараметром_Delgate Created;

    public event СобытиеСПараметром_Delgate Deleted;

    public event СобытиеСПараметром_Delgate Error;

    public event СобытиеСПараметром_Delgate Renamed;

    public event СобытиеСПараметром_Delgate Disposed;

 

    private Object thisLock = newObject();

 

 

    void ОтослатьСобытие(Событие_Delgate Событие, string ИмяСобытия)

    {

 

 

        Task.Run(() =>

        {

            if (Событие != null) //Событие();

            {

                lock (thisLock)

                {

 

                    try

                    {

                        Sc.Send(d => Событие(), null);

                    }

 

                    catch (Exception ex)

                    {

                        try

                        {

 

                            Sc.Send(d => ОшибкаСобытия(ИмяСобытия, null, AutoWrap.ОбернутьОбъект(ex)), null);

                        }

                        catch (Exception)

                        {

                        }

 

                    }

                }

            }

        });

    }

 

    void ОтослатьСобытиеСПараметром(СобытиеСПараметром_Delgate Событие, object value, string ИмяСобытия)

    {

        Task.Run(() =>

        {

 

 

            if (Событие != null) //Событие();

            {

                lock (thisLock)

                {

                    try

                    {

                        Sc.Send(d => Событие(AutoWrap.ОбернутьОбъект(value)), null);

                    }

                    catch (Exception ex)

                    {

                        try

                        {

 

                            Sc.Send(d => ОшибкаСобытия(ИмяСобытия, AutoWrap.ОбернутьОбъект(value), AutoWrap.ОбернутьОбъект(ex)), null);

                        }

                        catch (Exception)

                        {

                        }

                    }

 

                }

            }

        });

 

 

    }

    public ВрапперДляSystem_IO_FileSystemWatcher(object AutoWrap, System.IO.FileSystemWatcher РеальныйОбъект)

    {

 

        if (SynchronizationContext.Current == null)

            SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());

 

        Sc = SynchronizationContext.Current;

 

 

        this.РеальныйОбъект = РеальныйОбъект;

        this.AutoWrap = AutoWrap;

        РеальныйОбъект.Changed += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Changed, new { sender = sender, e = e }, "Changed");

        };

 

        РеальныйОбъект.Created += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Created, new { sender = sender, e = e }, "Created");

        };

 

        РеальныйОбъект.Deleted += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Deleted, new { sender = sender, e = e }, "Deleted");

        };

 

        РеальныйОбъект.Error += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Error, new { sender = sender, e = e }, "Error");

        };

 

        РеальныйОбъект.Renamed += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Renamed, new { sender = sender, e = e }, "Renamed");

        };

 

        РеальныйОбъект.Disposed += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Disposed, new { sender = sender, e = e }, "Disposed");

        };

 

 

    }

 

    public static object СоздатьОбъект(object AutoWrap, System.IO.FileSystemWatcher РеальныйОбъект)

    {

 

        return new ВрапперДляSystem_IO_FileSystemWatcher(AutoWrap, РеальныйОбъект);

    }

}

Так для упрощения, если параметров больше одного они упаковываются в анонимный класс.

Для вызова событий вызывается один из двух метод для всех событий с параметром и без.

Для вызова события в 1С используется SynchronizationContext для вызова в потоке 1С приложения.

Используется синхронизация на всякий случай и при возникновении ошибки при вызове метода 1С вызывается событие ОшибкаСобытия, так как такие ошибки 1С 8.х не отлавливает без секции попытка-исключение.

Параметры оборачиваются в объект типа AutoWrap  с помощью  AutoWrap.ОбернутьОбъект для использования объектов Net как объектов автоматизации

Модуль для 8 ки формируется такой

 

Перемврап,ОберткаСобытий;

Процедура СоздатьОбертку(объект)
 
//Динамически компилируется модуль C#
ОберткаСобытий=врап.СоздатьОберткуДляСобытий(объект);
// Добавляются обработчики
ДобавитьОбработчик ОберткаСобытий.ОшибкаСобытия,ОшибкаСобытия;


ДобавитьОбработчик ОберткаСобытий.Changed, Changed;
ДобавитьОбработчик ОберткаСобытий.Created, Created;
ДобавитьОбработчик ОберткаСобытий.Deleted, Deleted;
ДобавитьОбработчик ОберткаСобытий.Error, Error;
ДобавитьОбработчик ОберткаСобытий.Renamed, Renamed;
ДобавитьОбработчик ОберткаСобытий.Disposed, Disposed;
КонецПроцедуры
// Дается описание параметров, чтобы было проще к ним обращаться


//ИмяСобытия:String Имя События в котором произошло исключение
//Данные:object Параметры события
//ИсключениеСобытия:Exception Ошибка произошедшая при вызове события
Процедура ОшибкаСобытия(ИмяСобытия,Данные,ИсключениеСобытия)
    Сообщить("Не обработано событие "+ИмяСобытия);
     Сообщить(" Исключение "+Врап.ВСтроку(ИсключениеСобытия));
 Сообщить(" Данные "+Врап.ВСтроку(Данные));
            КонецПроцедуры
//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.IO.FileSystemEventArgs

            Процедура Changed(Данные)
               Сообщить("Changed "+Врап.ВСтроку(Данные));
            КонецПроцедуры

//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.IO.FileSystemEventArgs

            Процедура Created(Данные)
               Сообщить("Created "+Врап.ВСтроку(Данные));
            КонецПроцедуры

//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.IO.FileSystemEventArgs

            Процедура Deleted(Данные)
               Сообщить("Deleted "+Врап.ВСтроку(Данные));
            КонецПроцедуры

//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.IO.ErrorEventArgs

            Процедура Error(Данные)
               Сообщить("Error "+Врап.ВСтроку(Данные));
            КонецПроцедуры

//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.IO.RenamedEventArgs

            Процедура Renamed(Данные)
               Сообщить("Renamed "+Врап.ВСтроку(Данные));
            КонецПроцедуры

//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.EventArgs

            Процедура Disposed(Данные)
               Сообщить("Disposed "+Врап.ВСтроку(Данные));
            КонецПроцедуры

 

Так как в 7.7 нет возможности использования комовских событий, сделал обертку с использование вызова IAsyncEvent метода ExternalEvent

 

 

using System;

using System.Runtime.InteropServices;

using System.Windows.Forms;

using System.Threading;

using System.Threading.Tasks;

 

[Guid("ab634004-f13d-11d0-a459-004095e1daea"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

public interface IAsyncEvent

{

    void SetEventBufferDepth(int lDepth);

    void GetEventBufferDepth(refint plDepth);

    void ExternalEvent(string bstrSource, string bstrMessage, string bstrData);

    void CleanBuffer();

}

 

public class ВрапперДляSystem_IO_FileSystemWatcher77

{

    System.IO.FileSystemWatcher РеальныйОбъект;

    publicobject Changed;

    publicobject Created;

    publicobject Deleted;

    publicobject Error;

    publicobject Renamed;

    publicobject Disposed;

 

 

    dynamic AutoWrap;

    private SynchronizationContext Sc;

    IAsyncEvent СобытиеДля1С;

    privateObject thisLock = newObject();

    public object ПоследняяОшибка;

    public ВрапперДляSystem_IO_FileSystemWatcher77(object AutoWrap, ObjectГлобальныйКонтекст, System.IO.FileSystemWatcher РеальныйОбъект)

    {

 

        СобытиеДля1С = ГлобальныйКонтекст as IAsyncEvent;

        if (SynchronizationContext.Current == null)

            SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());

 

        Sc = SynchronizationContext.Current;

 

 

        this.РеальныйОбъект = РеальныйОбъект;

        this.AutoWrap = AutoWrap;

        РеальныйОбъект.Changed += (sender, e) =>

        {

            Changed = new { sender = sender, e = e };

            ОтослатьСобытие("Changed");

        };

 

        РеальныйОбъект.Created += (sender, e) =>

                    {

                        Created = new { sender = sender, e = e };

                        ОтослатьСобытие("Created");

                    };

 

        РеальныйОбъект.Deleted += (sender, e) =>

                    {

                        Deleted = new { sender = sender, e = e };

                        ОтослатьСобытие("Deleted");

                    };

 

        РеальныйОбъект.Error += (sender, e) =>

                    {

                        Error = new { sender = sender, e = e };

                        ОтослатьСобытие("Error");

                    };

 

        РеальныйОбъект.Renamed += (sender, e) =>

                    {

                        Renamed = new { sender = sender, e = e };

                        ОтослатьСобытие("Renamed");

                    };

 

        РеальныйОбъект.Disposed += (sender, e) =>

                    {

                        Disposed = new { sender = sender, e = e };

                        ОтослатьСобытие("Disposed");

                    };

 

 

 

    }

 

    void ОтослатьСобытие(string ИмяСобытия)

    {

 

 

        Task.Run(() =>

        {

 

            lock (thisLock)

            {

 

                try

                {

                    Sc.Send(d => СобытиеДля1С.ExternalEvent("System_IO_FileSystemWatcher", ИмяСобытия, ""), null);

                }

 

                catch (Exception ex)

                {

                    try

                    {

                        ПоследняяОшибка = new { Событие = ИмяСобытия, Исключение = ex };

                        Sc.Send(d => СобытиеДля1С.ExternalEvent("System_IO_FileSystemWatcher", "ОшибкаСобытия", ""), null);

                    }

                    catch (Exception)

                    {

                    }

 

                }

            }

 

        });

    }

 

    public static object СоздатьОбъект(object AutoWrap, Object ГлобальныйКонтекст, System.IO.FileSystemWatcher РеальныйОбъект)

    {

 

        return new ВрапперДляSystem_IO_FileSystemWatcher77(AutoWrap, ГлобальныйКонтекст, РеальныйОбъект);

    }

}

 

 

Для каждого события с параметром, параметрами создается одноименное поле и при возникновении события можно из 1С обратиться к этим полям.

Отмечу, что в данном случае объекты не оборачиваются в AutoWrap, так как обертка возвращается как AutoWrap. Поясню чуть позже

Перемврап,ОберткаСобытий;

Функция СоздатьОбертку(ОбертываемыйОбъект)

// В NetObjetToIDispatch.dllреализованклассВКpublicclassGlobalContext1C :IInitDone, ILanguageExtender

//для получения глобального контекста при вызове

// publicvoid Init([MarshalAs(UnmanagedType.IDispatch)]
//     object connection)
//    {
//        глобальныйКонтекст = connection;
//        Marshal.GetIUnknownForObject(глобальныйКонтекст);
//  }

 
    ПодключитьВнешнююКомпоненту("AddIn.GlobalContext1C");
    объект = СоздатьОбъект("AddIn.GlobalContext1C");
    ГлобальныйКонтекст= объект.ГлобальныйКонтекст;

    ОберткаСобытий= врап.СоздатьОберткуДляСобытий77(ОбертываемыйОбъект,ГлобальныйКонтекст);
КонецФункции // СоздатьОбертку



// Свойства ОберткаСобытий.ПоследняяОшибка
//Событие:String Имя События в котором произошло исключение
//Данные:object Параметры события
//ИсключениеСобытия:Exception Ошибка произошедшая при вызове события
Функция ОшибкаСобытия()
    ПоследняяОшибка=ОберткаСобытий.ПоследняяОшибка;
    Сообщить("Не обработано событие "+ПоследняяОшибка.Событие);
    Сообщить(Врап.ВСтроку(Шаблон("[ОберткаСобытий." + ПоследняяОшибка.Событие+ "]")));
    Сообщить("Ошибка");
    Сообщить(врап.ВСтроку(ПоследняяОшибка.Исключение))
КонецФункции
//  Свойства ОберткаСобытий.Changed
// sender:System.Object
// e:System.IO.FileSystemEventArgs

Функция Changed()
    Сообщить("Changed "+Врап.ВСтроку(ОберткаСобытий.Changed));
КонецФункции

//  Свойства ОберткаСобытий.Created
// sender:System.Object
// e:System.IO.FileSystemEventArgs

Функция Created()
    Сообщить("Created "+Врап.ВСтроку(ОберткаСобытий.Created));
КонецФункции

//  Свойства ОберткаСобытий.Deleted
// sender:System.Object
// e:System.IO.FileSystemEventArgs

Функция Deleted()
    Сообщить("Deleted "+Врап.ВСтроку(ОберткаСобытий.Deleted));
КонецФункции

//  Свойства ОберткаСобытий.Error
// sender:System.Object
// e:System.IO.ErrorEventArgs

Функция Error()
    Сообщить("Error "+Врап.ВСтроку(ОберткаСобытий.Error));
КонецФункции

//  Свойства ОберткаСобытий.Renamed
// sender:System.Object
// e:System.IO.RenamedEventArgs

Функция Renamed()
    Сообщить("Renamed "+Врап.ВСтроку(ОберткаСобытий.Renamed));
КонецФункции

//  Свойства ОберткаСобытий.Disposed
// sender:System.Object
// e:System.EventArgs

Функция Disposed()
    Сообщить("Disposed "+Врап.ВСтроку(ОберткаСобытий.Disposed));
КонецФункции




Процедура ПриОткрытии()
    врап=СоздатьОбъект("NetObjectToIDispatch45");

КонецПроцедуры // ПриОткрытии
//======================================================================
Процедура ОбработкаВнешнегоСобытия(Источник, ИмяСобытия, Данные)
    Если Источник = "System_IO_FileSystemWatcher" Тогда

        Шаблон("[" + ИмяСобытия+ "()]");
    КонецЕсли;
КонецПроцедуры // ОбработкаВнешнегоСобытия

Динамическая компиляция происходит следующим образом

 

public class КомВраперДляСобытий<T>

        {

        private static MethodInfo cоздательОбертки = null;

        private static MethodInfo cоздательОбертки77 = null;

 

       static CompilerResults СкомпилироватьОбертку(string строкаКласса,string ИмяКласса)

        {

           

          

            bool ЭтоСборкаГак = typeof(T).Assembly.GlobalAssemblyCache;

            string Путь = Path.GetDirectoryName(typeof(T).Assembly.Location);

           

 

 

            string OutputAssembly = Path.Combine(Путь, ИмяКласса) + ".dll";

       

         

            var compiler = new CSharpCodeProvider();

            var parameters = new CompilerParameters();

 

            parameters.ReferencedAssemblies.Add("System.dll");

            parameters.ReferencedAssemblies.Add("System.Core.dll");

            parameters.ReferencedAssemblies.Add("Microsoft.CSharp.dll");

            parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");

            parameters.ReferencedAssemblies.Add(typeof(AutoWrap).Assembly.Location);

 

            if (!ЭтоСборкаГак)

                parameters.ReferencedAssemblies.Add(typeof(T).Assembly.Location);

            else

            {

                string ИмяСборки = typeof(T).Assembly.ManifestModule.Name;

                if (parameters.ReferencedAssemblies.IndexOf(ИмяСборки) == -1)

                    parameters.ReferencedAssemblies.Add(ИмяСборки);

 

 

            }

 

            if (ЭтоСборкаГак)

                parameters.GenerateInMemory = true;

            else

            { //  parameters.GenerateInMemory = true;

                parameters.GenerateInMemory = false;

                parameters.OutputAssembly = OutputAssembly;

            }

 

            parameters.GenerateExecutable = false;

            parameters.IncludeDebugInformation = true;

 

            var res = compiler.CompileAssemblyFromSource(parameters, строкаКласса);

            return res;

        }

        public static MethodInfo СоздательОбертки { get {

                if (cоздательОбертки==null)

                {

                    Type типРеальногоОбъекта = typeof(T);

                    string ТипСтрРеальногоОбъекта = типРеальногоОбъекта.FullName;

                    var ИмяКласса = "ВрапперДля" + ТипСтрРеальногоОбъекта.Replace(".", "_").Replace("+", "_");

                   string  строкаКласса = ДляСозданияМодуляВрапераоздатьОписания(типРеальногоОбъекта);

                    var res = СкомпилироватьОбертку(строкаКласса,ИмяКласса);

 

                    Type тип = res.CompiledAssembly.GetType(ИмяКласса);

                    MethodInfo mi = тип.GetMethod("СоздатьОбъект", new Type[]{typeof(object),типРеальногоОбъекта });

                   

                    cоздательОбертки = mi;

                }

 

                return cоздательОбертки;

            } }

 

        public static MethodInfo СоздательОбертки77

        {

            get

            {

                if (cоздательОбертки77 == null)

                {

                    Type типРеальногоОбъекта = typeof(T);

                    string ТипСтрРеальногоОбъекта = типРеальногоОбъекта.FullName;

                    var ИмяКласса = "ВрапперДля" + ТипСтрРеальногоОбъекта.Replace(".", "_").Replace("+", "_")+"77";

                    string строкаКласса = ДляСозданияМодуляВрапераоздатьОписания77(типРеальногоОбъекта);

                    var res = СкомпилироватьОбертку(строкаКласса, ИмяКласса);

 

                    Type тип = res.CompiledAssembly.GetType(ИмяКласса);

                    MethodInfo mi = тип.GetMethod("СоздатьОбъект", new Type[] { typeof(object), typeof(object), типРеальногоОбъекта });

 

                    cоздательОбертки77 = mi;

                }

 

                return cоздательОбертки77;

            }

        }

 

Так, чтобы лишний раз не компилировать, закэшируем результат компиляции через свойство дженерик класса. Реализацию этого класса Net будет создавать при первом обращении, а статические поля будем заполнять компиляцией динамически создаваемого модуля на C# только раз для каждого типа.

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

 

Вызов из 1С происходит с помощью 2 методов СоздатьОберткуДляСобытий или СоздатьОберткуДляСобытий77

MethodInfo ПолучитьMethodInfoОберткиСобытий(string ИмяСвойства, object РеальныйОбъект)

        {

 

//      получаем дженерик тип КомВраперДляСобытий<> и указывем тип

 

            Type тип = РеальныйОбъект.GetType();

            Type genType = typeof(КомВраперДляСобытий<>);

            Type constructed = genType.MakeGenericType(new Type[] { тип });

 

            // Nowнаходим свойство и получаем его значение

            PropertyInfo pi = constructed.GetProperty(ИмяСвойства);

            MethodInfo функция = (MethodInfo)pi.GetValue(null, null);

            return функция;

 

        }

        public object СоздатьОберткуДляСобытий(object объект)

        {

 

            object РеальныйОбъект = AutoWrap.ПолучитьРеальныйОбъект(объект);

            var функция = ПолучитьMethodInfoОберткиСобытий("СоздательОбертки", РеальныйОбъект);

            object обертка = функция.Invoke(null,new object[] { this,РеальныйОбъект });

// Возвращаем реальный объект, так как он является COM объектом

            return обертка;

 

        }

        public object СоздатьОберткуДляСобытий77(object объект, object ГлобальныйКонтекст)

        {

 

            object РеальныйОбъект = AutoWrap.ПолучитьРеальныйОбъект(объект);

            var функция = ПолучитьMethodInfoОберткиСобытий("СоздательОбертки77", РеальныйОбъект);

            object обертка = функция.Invoke(null, new object[] {ГлобальныйКонтекстеальныйОбъект });

// Оборачиваем обертку событий в AutoWrap для использования в 1С как объекта автоматизации

            return AutoWrap.ОбернутьОбъект(обертка);

 

        }

 

Кроме того, можно использовать DynamicMethod. В отличие от динамической компиляции сборки,  определяет и представляет динамический метод, который может быть скомпилирован, выполнен и удалендаленные методы доступны для сборки мусора.

 

Так, в 1С нет операторов для битовых операций.  Для работы с FileSystemWatcher

Нам нужно определить события которые мы хотим отслеживать. На C# это выглядит так.

watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite

                   | NotifyFilters.FileName | NotifyFilters.DirectoryName;

 

Создадим функцию в C# проекте

public static NotifyFilters OR(NotifyFilters val1, NotifyFilters val2)

        {

 

            return val1 | val2;

        }

Скомпилирует

В ILSpyнайдемнашметодивыберемязыкдекомпиляции IL

.method public hidebysig static 
    valuetype [System]System.IO.NotifyFilters OR (
        valuetype [System]System.IO.NotifyFilters val1,
        valuetype [System]System.IO.NotifyFilters val2
    ) cil managed 
{
    // Method begins at RVA 0x20cc
    // Code size 9 (0x9)
    .maxstack 2
    .locals init (
        [0] valuetype [System]System.IO.NotifyFilters
    )

    IL_0000: nop
    IL_0001: ldarg.0
    IL_0002: ldarg.1
    IL_0003: or
    IL_0004: stloc.0
    IL_0005: br.s IL_0007

    IL_0007: ldloc.0
    IL_0008: ret
} // end of method MainWindow::OR

 

Для получения кода на MSIL можно использовать:

 Для рефлектора есть дизассемблер в Reflection.Emit, можно попытать щастья с expression trees (exp trees и emit состыковываются через CompileToMethod)

Также рекомендую вводную серию статей — тынц.

http://rsdn.ru/forum/dotnet/6235398.1

Большая благодарность Sinix

Так, используя старый Reflector и плагин ReflectionEmitLanguage.zip  можно получить следующий код

 

public MethodBuilder BuildMethodOR(TypeBuilder
type)
{
    // Declaring method builder
    // Method attributes
    System.Reflection.MethodAttributes methodAttributes = 
          System.Reflection.MethodAttributes.Public
        | System.Reflection.MethodAttributes.HideBySig
        | System.Reflection.MethodAttributes.Static;
    MethodBuildermethod = type.DefineMethod("OR", methodAttributes);
    // Preparing Reflection instances
    // Setting return type
    method.SetReturnType(typeof(NotifyFilters));
    // Adding parameters
    method.SetParameters(
        typeof(NotifyFilters),
        typeof(NotifyFilters)
        );
    // Parameter val1
    ParameterBuilderval1 =  method.DefineParameter(1, ParameterAttributes.None, "val1");
    // Parameter val2
    ParameterBuilderval2 =  method.DefineParameter(2, ParameterAttributes.None, "val2");
    ILGeneratorgen =  method.GetILGenerator();
    // Preparing locals
    LocalBuilderfilters =  gen.DeclareLocal(typeof(NotifyFilters));
    // Preparing labels
    Labellabel7 =  gen.DefineLabel();
    // Writing body
    gen.Emit(OpCodes.Nop);
    gen.Emit(OpCodes.Ldarg_0);
    gen.Emit(OpCodes.Ldarg_1);
    gen.Emit(OpCodes.Or);
    gen.Emit(OpCodes.Stloc_0);
    gen.Emit(OpCodes.Br_S,label7);
    gen.MarkLabel(label7);
    gen.Emit(OpCodes.Ldloc_0);
    gen.Emit(OpCodes.Ret);
    // finished
    return method;

 

 

 

И соответственно напишем это все на языке 1С

Функция ПолучитьМетод()
  //"System.Func`3"

  NotifyFilters=врап.ПолучитьТип("System.IO.NotifyFilters");
  helloArgs=врап.СоздатьМассив(врап.ПолучитьТип("System.Type"),2);
  helloArgs.SetValue(NotifyFilters,0);
  helloArgs.SetValue(NotifyFilters,1);

  ТипДляМодуля=Врап.ТипКакОбъект(врап.ПолучитьТип("System.String"));
  hello= врап.СоздатьОбъект("System.Reflection.Emit.DynamicMethod","OR",
  NotifyFilters,
  helloArgs,
  ТипДляМодуля.Module);


  il= hello.GetILGenerator();


  il.DeclareLocal(NotifyFilters); 
  iL0007Label= il.DefineLabel();

  OpCodes=врап.ПолучитьТип("System.Reflection.Emit.OpCodes");
  
  il.Emit(OpCodes.Nop);
  il.Emit(OpCodes.Ldarg_0);
  il.Emit(OpCodes.Ldarg_1);

  il.Emit(OpCodes.Or);
  il.Emit(OpCodes.Stloc_0);
  il.Emit(OpCodes.Br_S, iL0007Label);
  il.MarkLabel(iL0007Label);
  il.Emit(OpCodes.Ldloc_0);
  il.Emit(OpCodes.Ret);
  тип = врап.ПолучитьТип("System.Func`3");
  типДелегата= Врап.ТипКакОбъект(тип).MakeGenericType(NotifyFilters,NotifyFilters,NotifyFilters);
  res= hello.CreateDelegate(типДелегата
  returnres

КонецФункции

Функция Или2(вал1,вал2)
  возврат врап.ВыполнитьДелегат(ДелегатИЛИ,вал1,вал2);
  //ДелегатИЛИ.DynamicInvoke(вал1,вал2);

КонецФункции// гл

Процедура КнопкаВыполнитьНажатие(Кнопка)
  // Вставить содержимое обработчика.
  Остановить();

    watcher= врап.СоздатьОбъект("System.IO.FileSystemWatcher, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
    Директория="c:\tmp\";
    watcher.Path= Директория;
       // Only watch text files.

    ДелегатИЛИ=ПолучитьМетод();
    NotifyFilters=врап.ПолучитьТип("System.IO.NotifyFilters");
//watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
    //        | NotifyFilters.FileName | NotifyFilters.DirectoryName;
    рез=Или2(NotifyFilters.LastAccess,Или2(NotifyFilters.LastWrite,Или2(NotifyFilters.FileName,NotifyFilters.DirectoryName)));
    watcher.NotifyFilter=рез;
    watcher.Filter= "*.*";
    watcher.IncludeSubdirectories= true;

    watcher.EnableRaisingEvents= true;

    СоздатьОбертку(watcher);


КонецПроцедуры

 

Так полностью можно исключить внешние сборки. Мало того, сейчас на подходе релиз scripting api.

https://github.com/dotnet/roslyn/tree/master/src/Scripting/Core
Вот неплохое введение, всю серию статей можно смело читать, вредным не будет.

https://joshvarty.wordpress.com/2015/10/15/learn-roslyn-now-part-14-intro-to-the-scripting-api/


UPD. И ещё статья вдогонку.

http://daveaglick.com/posts/compiler-platform-scripting

То есть вместо IL можно использовать

 

 

 То есть использование .Net в 1С станет достаточно простым.

 

Напоследок приведу пример использоваиня SerialPort для считывания Штрих-Кода

 

sp= Врап.СоздатьОбъект("System.IO.Ports.SerialPort","COM" + НомерПорта);
   
ПИ="System.IO.Ports.";
   
sp.BaudRate= 9600;
   
sp.Parity= Врап.ПолучитьТип(ПИ+"Parity").None;
   
sp.StopBits= Врап.ПолучитьТип(ПИ+"StopBits").One;
   
sp.DataBits= 8;
   
sp.Handshake= Врап.ПолучитьТип(ПИ+"Handshake").None;

   
СоздатьОбертку(sp);
   
sp.Open();

 

и обработка события

 

Процедура DataReceived(Данные)
    sp1 = Данные.sender;
    ШтрихКод= sp1.ReadExisting();
    Компорт= sp1.PortName;
    Сообщить(СтрШаблон("ШК=%1 Порт=%2",ШтрихКод,Компорт));

КонецПроцедуры

 

К проверял через SerialRedirectorиспользуя программы //firstportal.ru/public/14587/ .

Обработки для теста System.IO.FileSystemWatcher и получение текстов модулей для 1С и C# находятся в папке ВнешниеОтчеты

ТестКомпиляцииСобытий.ert

ТестСобытийИзмененийВДиректории.epf

TestSerialPort.epf для теста COM порта.

51

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. shakmaev 339 13.11.15 11:45 Сейчас в теме
Беда с оформлением статьи, и куда только смотрят модераторы?
гвость; +1 Ответить
2. Serginio 798 13.11.15 12:04 Сейчас в теме
(1) А по существу? Просто править текст очень тяжело.
3. cool.vlad4 45 13.11.15 12:20 Сейчас в теме
(2) статья полезная. только (1) прав. код c# можно было на pastebin разместить, а здесь ссылку оставить. (часть кода ис распарсил в ссылки )
5. Serginio 798 13.11.15 13:03 Сейчас в теме
(3) Спасибо. Учту и попробую
(4) Спасибо.
4. gortol 183 13.11.15 12:29 Сейчас в теме
зато открывает возможности описания собственных событий, очень полезная информация, мне не хватило информации из интернета как раз для формирования собственных событий и передать их в 1с...
6. ivanov660 1638 15.11.15 12:44 Сейчас в теме
Довольно забавно получается - надо писать 1Сом Сишарп.
На мой взгляд:
1. Надо не забывать о правах пользователя под которым собирается и компилируется код.
2. Необходимо не забывать про обработку ошибок при динамической компиляции.
3. Про версии .net при которых возможно использование данных возможностей - где-то от 3.5+ и выше.
4. Можно было просто передать текстовый кусок кода (*.cs) и скомпилировать его на лету.
8. Serginio 798 15.11.15 13:12 Сейчас в теме
(6) ivanov660,
1. Про пользователей согласен. Надо будет озаботиться System.Security.Permissions
2. В статье рассматривается динамическая компиляция для создания оболочки для использования свойств. Там ошибок нет.
Но можно использовать CompilerResults.Errors при использовании CompileAssemblyFromSource
При использовании своего кода при использовании CSharpCodeProvider из 1С.
3. В данном случае применяется 4.5.2 При использовании scripting api. наверное уже будет использоваться 4.6
4. Это можно просто использовать http://infostart.ru/public/238584/ NetObjectToIDispatch45 и использовать CSharpCodeProvider со всеми свойствами итд
33. MherArsh 24 13.09.16 23:35 Сейчас в теме
Привет всем!
Может кто то вкурсе?
Я написал COM объект, зарегистрировал, все вроде норм но вылезает ошибка.
Вопрос в том что я использую стотонную библиотеку в моей сборке, но она ежит вместе с основным dll но я все ровно получаю ошибку.

{ВнешняяОбработка.ВнешняяОбработка1.Форма.Форма.Форма(8)}: Ошибка при вызове метода контекста (Login): Произошла исключительная ситуация (TestNative): Не удалось загрузить файл или сборку "RestSharp, Version=105.2.3.0, Culture=neutral, PublicKeyToken=null" либо одну из их зависимостей. Требуется сборка со строгим именем. (Исключение из HRESULT: 0x80131044)

7. delete 236 15.11.15 13:06 Сейчас в теме
То есть использование .Net в 1С станет достаточно простым.

Куда уж проще то (*сарказм*)

имхо, статья неплоха, но как-то написана больше для тех, кто в теме
ну и из-за оформления читать приходится через боль)
9. Serginio 798 15.11.15 13:22 Сейчас в теме
(7) delete, Ну ты же в теме. Да проблема в том, что мало 1С ников знает .Net и в частности C#. Это статья дополнение к http://infostart.ru/public/238584/ и сводится к использованию нетовских событий к использованию одной строчки
ОберткаСобытий=врап.СоздатьОберткуДляСобытий(объект);

Все остальное, это рассказ о том как формируется реальный код. То есть, для тех кому это интересно и использовать сгенеренный код для дальнейшей модификации или как использовать обвязку нетовских свойств для использования через ДобавитьОбработчик или ОбработкаВнешнегоСобытия. Думаю многим это будет полезным. За оформление прошу прощения. Спешил, да и дизайнерские способности у меня невысокие
10. cool.vlad4 45 15.11.15 23:13 Сейчас в теме
(9) да дизайнерские способности ни причем. я например вообще не хочу публиковать статьи на ис, поскольку публикация это боль (у меня процессор так грузился как не зная что, но может с тех пор ситуация изменилась) , ну и форматирование там так себе. насчет статьи, я напимер в теме. (некоторые свои вк, кстати публиковал, опять же по причине движка ис в комментах). но имхо с com есть некоторый геморрой при деплое. например, мне были бы интереснее вещи касательно обмена данных, генерации всяких dto между приложением на C# (какой-нибудь сервис) и 1С. тут нет никакой магии , но просто может есть наработки . и еще была бы интересна генерация именно 1С кода. и некоторый анализатор его . вот с шарпом как раз таки проблем тут нет. (учитывая что Roslyn уже есть)
11. Serginio 798 15.11.15 23:52 Сейчас в теме
(10) Я пишу в ворде. Затем сохраняю в HTML и загружаю уже на ИС. Корректировать проблема. Удаляются пробелы. Согласен, что что то добавить или отредактировать это проблема. По поводу COM проблем не вижу. И это единственный способ (кроме Native ВК) интеграции 1С с манагед кодом. Кстати начал использовать http://infostart.ru/public/238584/ тогда, когда из 1С не смог достучаться до C# сервисов на по WS- протоколам итд. Там была развитая система классов, и описывать всех из через СОМ было муторно. Через обертку IReflect оказалось значительно проще
А так, это расширение языка без написания ВК. Использутся только COMОбъект("NetObjectToIDispatch45");
Конечно было бы чудесно, если бы 1С включила его в дистрибутив, что бы не надо было отдельно его регистрировать
12. cool.vlad4 45 16.11.15 00:03 Сейчас в теме
(11) регистрация это и есть проблема. админам это доверять не всегда хочется. а вручную самому во-первых нет смысла этим заниматься, а во-вторых не всегда есть соотвествующие права на ветки реестра.
13. Serginio 798 16.11.15 00:06 Сейчас в теме
(12) Так зарегистрировать нужно только NetObjectToIDispatch45. И будет открыт доступ ко всем Net овским классам, где регистрация не нужна
14. cool.vlad4 45 16.11.15 00:15 Сейчас в теме
(13) это то понятно. (аналогично как и у Elisy своя ВК или у ObjectFerm авторство не помню чье). только код будет specific, поскольку в некоторых конторах есть админы , которые просто откажутся что-то регистрировать, то что по их мнению доверия не заслуживает. и получится две версии кода, одна с ВК, другая без ВК и головная боль.
23. avz_1C 10 16.02.16 12:38 Сейчас в теме
(7) delete,

Спасибо от тех, "кто в теме" :-)

Очень грамотно пишете, читаю с удовольствием!
15. Serginio 798 16.11.15 00:20 Сейчас в теме
Использовать COM это необязательно регистрация. Можно сделать ВК (а они есть) которя будет грузить DLL и по гуиду доставать нужный IDispatch. Пример использования кстати есть в http://infostart.ru/public/238584/
16. Aphanas 138 17.11.15 19:21 Сейчас в теме
Други, простите великодушно, тут, видимо не для средних умов. Интересуюсь темой подписки на события через "ДобавитьОбработчик". Не могу врубиться, что делает эта разработка? Объясните кто-нибудь на простом языке. Я вижу кучу кода на C#, но куда всё это надо толкать, я так и не понял. И как это потом к "ДобавитьОбработчик" прикручивать?
17. Serginio 798 17.11.15 23:28 Сейчас в теме
(16) Это надо скачать http://infostart.ru/public/238584/ там есть обработки с генерацией 1С кода для подключения события.
И смотри пример с SerialPort для считывания Штрих-Кода.
Куча кода на C# объясняет только одну строку ОберткаСобытий=врап.СоздатьОберткуДляСобытий(объект);
18. Serginio 798 18.12.15 10:33 Сейчас в теме
Можно повторно использовать скомпилированную сборку. Например использовано здесь 1C Messenger для отправки сообщений, файлов и обмена данными между пользователями 1С, вэб страницы, мобильными приложениями а ля Skype, WhatsApp

Процедура ПолучитьОбертку(NetОбъект)
        
        // Использовал методы .Net классов для того, что бы показать технику использования обертки .Net классов
        Если не Объект.ИспользоватьСкомпилированнуюСборку Тогда
               ОберткаСобытий=врап.СоздатьОберткуДляСобытий(NetОбъект);
               возврат
        КонецЕсли; 
        //Так как сборка компилируется в реальную DLL, то если сборка SignalRHelloClient.dll не менялась, то и обертку событий компилировать не нужно 
        
        
        // Используем ТипКакОбъект для получения методов Type
        // По умолчанию для типа используются статические методы
        Тип=Врап.ТипКакОбъект(NetОбъект.GetType());
        ИмяФайлаСборки = тип.Assembly.Location;
        Path=Врап.ПолучитьТип("System.IO.Path");
        Каталог = Path.GetDirectoryName(ИмяФайлаСборки);
        
        ТипСтрРеальногоОбъекта = тип.FullName;
        // Применим метод ОбернутьЛюбойОбъект для получения методов String
        // Так как String возвращается без обертки
        ИмяКласса = "ВрапперДля" + Врап.ОбернутьЛюбойОбъект(Врап.ОбернутьЛюбойОбъект(ТипСтрРеальногоОбъекта).Replace(".", "_")).Replace("+", "_");
        OutputAssembly = Path.Combine(Каталог, ИмяКласса) + ".dll";
        
        Если  Врап.ПолучитьТип("System.IO.File").Exists(OutputAssembly) Тогда
               ТипОбертки=Врап.ПолучитьТипИзСборки(ИмяКласса,OutputAssembly);
               
               // У типа ТипОбертки есть статический метод  СоздатьОбъект который принимает обертываемый объект
               Попытка
               объектОбертка=ТипОбертки.СоздатьОбъект(Врап,NetОбъект);
        Исключение
               врап.ВывестиПоследнююОшибку()
               КонецПопытки;
               // Нужно получить COM объект из обертки
               ОберткаСобытий=Врап.ПолучитьРеальныйОбъект(объектОбертка);
        Иначе
               // Нет скомпилированной DLL     
               ОберткаСобытий=врап.СоздатьОберткуДляСобытий(NetОбъект);
               
        КонецЕсли; 
        
        
        
        
КонецПроцедуры // ПолучитьОбертку()
Показать
19. Makushimo 154 21.12.15 09:48 Сейчас в теме
я не в теме.
и мне ничего не понятно.
20. Serginio 798 21.12.15 09:58 Сейчас в теме
Это обертка над нетовскими классами. Мое описание больше для знакомых с нетовскими классами.
Есть пример использования класса DateTime для конвертации данных из строки в дату
http://infostart.ru/public/434345/

У нетовских классов есть события. Которые можно использовать переводя их в Комовские или использовать как внешнее событие. Так или иначе нужно знать какие события есть у класса.

Например из примера
FileSystemWatcher это нетовский объект следящий за изменением директории
Все его свойства, методы и события можно посмотреть здесь
https://msdn.microsoft.com/ru-ru/library/system.io.filesystemwatcher(v=vs.110).aspx
21. Serginio 798 21.12.15 11:13 Сейчас в теме
А если убрать C# код то суть всей этой стать состоит в вызове методов

ОберткаСобытий=врап.СоздатьОберткуДляСобытий(объект);


или
ПодключитьВнешнююКомпоненту("AddIn.GlobalContext1C");
    объект = СоздатьОбъект("AddIn.GlobalContext1C");
    ГлобальныйКонтекст= объект.ГлобальныйКонтекст;

    ОберткаСобытий= врап.СоздатьОберткуДляСобытий77(ОбертываемыйОбъект,ГлобальныйКонтекст);
22. Serginio 798 21.01.16 14:10 Сейчас в теме
Поигрался со Scripting-API https://github.com/dotnet/roslyn/wiki/Scripting-API-Samples#exprstrong

Создал сборку. Проинсталировал
Install-Package Microsoft.CodeAnalysis.Scripting

Создал класс
namespace ScriptApiDlls

{ 
   public class КлассДляВычесленияВыражений 
    { 
      public static  Microsoft.CodeAnalysis.Scripting.ScriptOptions Опции { get { return Microsoft.CodeAnalysis.Scripting.ScriptOptions.Default; } } 
       
        public static object Вычислить(string Код, Microsoft.CodeAnalysis.Scripting.ScriptOptions опции ) 
        { 
            return Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.EvaluateAsync(Код, опции).Result;

        }

    } 
}
Показать



Теперь можно на примере регулярных выражений создать делегат и использовать его в Replace. Например для того, что бы все слова начинались с заглавной буквы
врап=новый COMОбъект("NetObjectToIDispatch45");
    Match=Врап.ПолучитьТипИзСборки("System.Text.RegularExpressions.Match","System.dll");
    Regex=Врап.ПолучитьТип("System.Text.RegularExpressions.Regex");

    КлассДляВычесленияВыражений=Врап.ПолучитьТипИзСборки("ScriptApiDlls.КлассДляВычесленияВыражений",ПутьКДлл+"ScriptApiDlls.dll");
    ScriptOptions=КлассДляВычесленияВыражений.Опции;
    
    Слова = "надо заменить все первые буквы в словах на заглавные";
    pattern = "\w+";
    // MatchEvaluator evaluator = (MatchEvaluator)ПолучитьДелегат();

    scr = ScriptOptions.Default.WithReferences(Врап.ТипКакОбъект(Match).Assembly)
    .WithImports("System", "System.Text.RegularExpressions");
    ТекстДелегата =  "return (MatchEvaluator)((match) =>
    |{
    |  string x = match.Value;
    // Если первая буква в нижнем регистре то заменяем на заглавную

    |if (char.IsLower(x[0]))
    |{
    |  // Capitalize it.

    |   return char.ToUpper(x[0]) + x.Substring(1, x.Length - 1);
    |}
    |return x;
    |
    |   });";
    
    evaluator = КлассДляВычесленияВыражений.Вычислить(ТекстДелегата,scr);
    Сообщить(Regex.Replace(Слова, pattern, evaluator));
Показать


В итоге получаем
Надо Заменить Все Первые Буквы В Словах На Заглавные
24. TeMochkiN 04.09.16 23:48 Сейчас в теме
У вас тут столько всего интересного :)
Правда у меня проблема :(
При вызове врап.СоздатьОберткуДляСобытий
возникает ошибка:
Произошла исключительная ситуация (mscorlib): Адресат вызова создал исключение.
честно говоря, даже не знаю куда смотреть, что проверять :(
25. Serginio 798 05.09.16 10:01 Сейчас в теме
Есть обработка ТестСобытийИзмененийВДиректории.epf Там есть пример и обработка формирования текстов модулей на C# и 1С.
Нужно выбрать полное имя класса и имя DLL/ Для не глобальных сборок нужно указывать полный путь. Все зависимые сборки должны быть в одной директории
26. TeMochkiN 05.09.16 10:24 Сейчас в теме
(25) вроде всё так и есть, все зависимые сборки в одной директории. Попытался посмотреть отладчиком вижуал студии, пишет такую вот ошибку:
Исключение типа "System.IO.FileNotFoundException" возникло в mscorlib.dll, но не было обработано в коде пользователя

Дополнительные сведения: Не удалось загрузить файл или сборку "file:///C:\Users\temochkin\Desktop\AsterNET.ARI-master\AsteriskFor1C\bin\Release\ВрапперДляAsterNET_ARI_AriC­lient.dll" либо одну из их зависимостей. Не удается найти указанный файл.




Однако, я вижу, что в этой папке успешно создались файлы ВрапперДляAsterNET_ARI_AriClient.dll и ВрапперДляAsterNET_ARI_AriClient.pdb

или всё-таки на отсутствие какой-то зависимой сборки может ругаться? я просто не знаю, как определить какой именно может не хватать.
27. Serginio 798 05.09.16 10:31 Сейчас в теме
Какой то DLL не хватает. Для чистоты эксперимента создай проект встрой туда ссылки на нужные DLL и текст для C# и скомпилируй сборку и её используй для подключения событий
29. TeMochkiN 05.09.16 11:03 Сейчас в теме
(27) у меня получилось, но только после того, как я все зависимые сборки загрузил с помощью врап.ЗагрузитьСборку(ПутьСборки)
30. Serginio 798 05.09.16 13:34 Сейчас в теме
(29) Обычно когда загружается основная сборка, она грузит и все от которых зависит. Спасибо. Буду иметь ввиду.
(28) Большое спасибо!
31. TeMochkiN 05.09.16 13:53 Сейчас в теме
(30) не знаю, может конечно я что-то неправильно делаю, но в любом случае спасибо вам, т.к. обертка событий у меня заработала :)
у вас вообще столько статей интересных, мне их ещё читать и читать)
32. Serginio 798 05.09.16 14:15 Сейчас в теме
(31) Спасибо! и на здоровье.
28. white-mount 05.09.16 10:50 Сейчас в теме
Статья понравилась, добавил в свой в список "избранного". Автору респект.
Код читаю в оригинальной среде, вопросов не возникает.
34. Serginio 798 14.09.16 00:01 Сейчас в теме
Видно еще каких то библиотек не хватает. Для начала попробовать загрузить из .Net приложения.
Возможно нужно поместить в GAC. https://msdn.microsoft.com/ru-ru/library/h4fa028b(v=vs.110).aspx
Я с этим не сталкивался
Оставьте свое сообщение

См. также

Регистры бухгалтерии. Общая информация 111

Статья Программист Нет файла v8 v8::БУ БУ Бесплатно (free) Практика программирования Математика и алгоритмы Разработка

Общая информация о внутреннем устройстве регистров бухгалтерии.

05.09.2019    6698    YPermitin    22       

"Хочу универсально!" [Часть 1] 65

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Математика и алгоритмы Практика программирования Разработка

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

02.09.2019    4900    SeiOkami    35       

Иерархия без "В ИЕРАРХИИ" 117

Статья Программист Нет файла v8 Бесплатно (free) Математика и алгоритмы

Говорится о том, как эффективно представлять иерархию в СУБД, как получать и использовать эти представления при решении задач в запросной технике. Уточняются и дополняются запросы из статьи "Уровни, глубина, прародители, циклы и аналоги запросом" [https://infostart.ru/public/160707/].

22.08.2019    4913    ildarovich    16       

EnterpriseData – часть 3. Загрузка данных, идентификация объектов 62

Статья Программист Нет файла v8 v8::УФ 1cv8.cf ОС Бесплатно (free) Практика программирования Математика и алгоритмы Перенос данных из 1C8 в 1C8 Разработка

Основные этапы загрузки данных через EnterpriseData. Идентификация объектов загружаемых полностью и по ссылке. Приведены схемы процессов загрузки данных. Описание основных операций и обработчиков. Перечень процедур БСП, используемых при загрузке данных, структура «КомпонентыОбмена».

22.08.2019    4230    ids79    7       

PinkRabbitMQ - Native API компонента 1С с открытым исходным кодом, для обмена сообщениями через RabbitMQ 137

Инструменты и обработки Программист Архив с данными v8 Бесплатно (free) Разработка внешних компонент

PinkRabbitMQ представляет собой Native API компоненту для 1С Предприятия 8 (Windows 32bit и 64bit) с открытым исходным кодом на с++ (можно собрать компоненту самостоятельно). PinkRabbitMQ это низкоуровневая компонента которая реализует обмен по протоколу AMQP с брокером сообщений RabbitMQ. Для организации высокоуровнего обмена между информационными базами предназначен Адаптер. Компонента разрабатывается в рамках проекта Адаптер.

29.07.2019    7140    445    Begemoth80    110       

Обработчики событий при записи объектов. Зачем и что за чем? 202

Статья Программист Нет файла v8 Бесплатно (free) Математика и алгоритмы

Программисту, имеющему немного опыта на платформе 1С 8.3, бывает сложно разобраться: ПередЗаписью, ПриЗаписи, ПослеЗаписи, на сервере, на клиенте, в модуле формы, в модуле объекта.... Эта шпаргалка была создана в процессе обучения и реального опыта с целью разложить всё по полочкам, чтобы было четкое понимание в каком случае какой обработчик нужно использовать и в какой последовательности они запускаются при записи и проведении документов. Данная статья будет полезна в большей степени начинающим разработчикам. Но и опытным позволит освежить информацию, упорядочить её.

25.07.2019    12801    4    AlbinaAAA    23       

FizzBuzz на 1С. Чем короче, тем веселее. Варианты принимаются... 8

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования Математика и алгоритмы Разработка

Мне было скучно, я не мог себя заставить написать ничего полезного. И читал статью на Хабре. Потом я читал комментарии, а потом... нет я не ушел смотреть котиков на ютюбе. Я решил сделать несколько решений задачки FizzBuzz на 1С, с целью "чем короче, тем лучше". Прошу сильно не пинать, это просто развлечение для вечера.

24.07.2019    2863    vandalsvq    16       

Управление качеством кода 136

Статья Программист Руководитель проекта Нет файла v8 Бесплатно (free) Математика и алгоритмы Рефакторинг и качество кода

О SonarQube, АПК, EDT. Какие преимущества дает их использование. Для каких команд подходит.

22.07.2019    8233    Stepa86    29       

Что делает "В ИЕРАРХИИ" в запросе? 94

Статья Программист Нет файла v8 Бесплатно (free) Математика и алгоритмы

Описание действий платформы 1С при использовании конструкции "В ИЕРАРХИИ" в запросах.

16.07.2019    8182    YPermitin    34       

Создание отчетов с помощью СКД - основные понятия и элементы 208

Статья Программист Нет файла v8 v8::СКД Бесплатно (free) Практика программирования Математика и алгоритмы

Основные принципы работы СКД. Понятия схемы компоновки и макета компоновки. Описание основных элементов схемы компоновки: наборы данных, поля, вычисляемые поля, ресурсы, параметры.

25.06.2019    20978    ids79    17       

Реализуем Стек, Очередь и Приоритетную очередь в 1С 52

Статья Программист Нет файла v8 1cv8.cf Россия Бесплатно (free) Практика программирования Математика и алгоритмы Разработка

В статье рассматриваются способы реализации таких абстрактных структур данных, как стек, очередь и приоритетная очередь, используя готовые типы данных 1С. Выявляются "узкие" места, сложные моменты в реализации и сравнивается скорость работы.

24.06.2019    7804    RonX01    63       

Вычисление 200 тысяч знаков числа pi 73

Статья Программист Нет файла v8 Россия Бесплатно (free) Математика и алгоритмы

В статье рассматриваются возможности платформы выполнять сверхточные вычисления без использования сложных алгоритмов и внешних компонент на примере вычисления числа pi.

28.05.2019    3983    Oleg_nsk    93       

Регистры накопления. Виртуальные таблицы. Часть №1: Обороты 84

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования Математика и алгоритмы Разработка

Описание работы платформы 1С:Предприятие 8.2 с виртуальной таблицей "Обороты" регистров накопления.

20.05.2019    11069    YPermitin    5       

Даем названия переменным: как префиксы экономят наше время 10

Статья Программист Стажер Внешняя обработка (ert,epf) v8 Бесплатно (free) Практика программирования Математика и алгоритмы Разработка

Понятные названия переменных экономят время и силы разработчика : в начале, когда мы даём названия переменным, в процессе развития разработки, когда мы "на лету" понимаем назначение той или иной переменной, в конце, когда мы передаём разработку на поддержку других программистов, сами переходя к новым разработкам

06.05.2019    3213    Designer1C    69       

Заметки по SQL: Срез последних - аналог запроса 15

Статья Программист Нет файла v8 1cv8.cf Россия Бесплатно (free) Практика программирования Математика и алгоритмы

В статье описывается создание среза последних данных средствами классического языка запросов. Причем метод построения запроса был разработан еще во времена, когда автор работал с СУБД Oracle 9i и программировал на PL SQL. Основная идея заключается преобразовании запроса с подзапросом, в запрос без подзапроса (в примерах описывается преобразование до двух вложенных подзапросов). Запросы тестировались на реальных базах данных. Платформа - 1С:Предприятие 8.3 (8.3.10.2561).

15.01.2019    6318    IVC_goal    5       

Автоматические и управляемые блокировки применительно к типовым конфигурациям 1С 127

Статья Программист Нет файла v8 v8::blocking 1cv8.cf Бесплатно (free) Математика и алгоритмы Практика программирования

Основные принципы работы с режимами автоматических и управляемых блокировок в 1С Предприятие 8. Теория и применение в типовых конфигурациях: БП, УТ, ЕРП

10.11.2018    22245    ids79    40       

Основные понятия и механизмы оптимизации клиент-серверного взаимодействия в 1C 147

Статья Программист Нет файла v8 Россия Бесплатно (free) Математика и алгоритмы Практика программирования

У многих начинающих 1С программистов часто возникают вопросы про клиент-серверное взаимодействие в 1С и чтобы разобраться в непростых механизмах платформы, необходимо понять, что же такое контекст, для чего предназначены директивы компиляции, что представляют собой контекстные/внеконтекстные вызовы и как наиболее оптимально описывать прикладные задачи в модулях управляемых форм.

23.08.2018    22869    Rain88    42       

Теорема номер тринадцать 15

Статья Программист Нет файла v8 Бесплатно (free) Математика и алгоритмы

Использование математических методов для языка запросов.

15.03.2018    9358    vasilev2015    24       

Введение в CI для 1С 87

Статья Программист Нет файла v8 Россия Бесплатно (free) Математика и алгоритмы

Значение роли тестирования при разработке ПО трудно переоценить, его применение позволяет повысить надёжность продукта и улучшить качество кода. Для продуктов для платформы 1С:Предприятие существует ряд инструментов для проведения тестирования, в том числе и от самого вендора. Но, также появились открытые инструменты, реализующие мировые практики проведения тестирования (проверки продукта), поддерживаемые сообществом. В этой статье описаны базовые принципы, которые необходимо понимать перед началом применения этих инструментов.

21.11.2017    19331    real_MaxA    22       

#Область ВНЕШНИЕ_ВЫЗОВЫ или MVC в 1С, библиотечность и упрощение интеграции кода 43

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования Математика и алгоритмы Универсальные функции

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

12.10.2017    14809    for_sale    58       

Групповая разработка конфигураций в крупном холдинге 68

Статья Программист Нет файла v8 Бесплатно (free) Математика и алгоритмы

О чем мы сегодня поговорим? • О становлении и развитии групповой разработки конфигураций 1С в крупном холдинге с использованием хранилища конфигураций. • Обсудим практически все аспекты использования хранилища в командной разработке. • Я расскажу про те методы и идеи, которые мы пробовали использовать, какие используем до сих пор, от каких отказались и почему.

15.08.2017    17545    stas_ganiev    15       

Автоматизация процесса 1С-разработки 91

Статья Программист Нет файла v8 Бесплатно (free) Математика и алгоритмы

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

07.06.2017    23028    ekaruk    9       

Пишем игру Минер. Обработка событий ActiveX в 1С 29

Статья Программист Нет файла v8 Россия Windows Бесплатно (free) Практика программирования Математика и алгоритмы

Пример демонстрирует обработку событий генерируемых компонентой ActiveX в 1С.

29.05.2017    12732    user621724_Dimav1979    11       

Как я доступ на kb.1c.ru получал 91

Статья Программист Нет файла v8 Россия Бесплатно (free) Решение задач на 1С:Специалист Математика и алгоритмы

kb.1c - база знаний по технологическим вопросам крупных внедрений и не только. В этой базе знаний собираются методики и решения технологических проблем эксплуатации 1с, check-list'ы и инструкции по настройке ПО на серверах. Какие-то из размещенных статей дублируются на ИТС. Когда я искал пути получения доступа к нему я столкнулся с проблемой: мало кто доподлинно знает как получить доступ к нему, не работая у франчайзи 1с. Я опишу путь, который прошёл я, как физическое лицо.

01.05.2017    22534    ikekoval    33       

Улучшение стандарта "Структура модуля" 6

Статья Программист Нет файла v8 1cv8.cf Россия Бесплатно (free) Математика и алгоритмы

Описывается структура областей модулей, которую я использую при разработке на своих проектах. Обсуждаются недостатки стандарта 1С "Структура модуля". Предложен улучшенный подход к работе со структурой модуля.

26.03.2017    12325    o.nikolaev    23       

"Распределение в запросе" или "избавляемся от перебора" 185

Статья Программист Нет файла v8 1cv8.cf Россия Бесплатно (free) Математика и алгоритмы Универсальные функции

Хороший перебор - это отсутствие перебора. Рассмотрим пример замены полного перебора запросом.

16.12.2016    28631    alexandersh    48       

Планы обмена. Квитировать или гарантировать? 24

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования Математика и алгоритмы

Планы обмена предлагают использовать две стратегии удаления обработанных изменений: квитирование и гарантированная доставка сообщений. Как сделать правильный выбор?

12.12.2016    14558    zhichkin    9       

Некоторые принципы оптимизации запросов 1С (+SQL) 115

Статья Программист Нет файла v8 Бесплатно (free) Математика и алгоритмы

Разработка нового функционала часто связана с созданием новых таблиц в базе и написанием запросов. Собственно, размышляя о запросах, мы и формируем в голове содержание таблиц, индексы и количество таблиц и индексов. Заранее можно уверенно рассуждать о том, какая нужна архитектура, если задачу удалось понять. На этом этапе важно привлекать свой опыт. Что же делать, если его нет? Как рассуждать о запросах и формате хранения?

17.11.2016    8898    ture    40       

Использование git для доработки типовых конфигураций 1С 230

Статья Программист Нет файла v8 Беларусь Украина Россия Бесплатно (free) Математика и алгоритмы

Рассмотрены способы доработок типовой конфигурации 1C для различных изменений, и на картинках продемонстрирован подход к разработке с использованием git и частично с тестами.

11.10.2016    188456    pumbaE    31       

Оптимизация запросов 1С:Предприятие – от теории к практике 116

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования Математика и алгоритмы

Я давно отметил достаточно серьезный интерес сообщества к вопросам оптимизации и повышения производительности высоконагруженных систем. Общаясь с различными специалистами, обслуживающими малые и большие предприятия (торговые и производственные), я пришел к выводу, что вопросы повышения производительности интересны почти всем, вне зависимости от того, какую конфигурацию они обслуживают – большую или маленькую, измененную или без значительных изменений. В связи с этим я пришел к выводу, что стоит посвятить данный материал вопросам оптимизации запросов, поскольку именно запросы являются основным инструментом извлечения данных из системы.

07.10.2016    32080    bpc222    20       

.Net Core, обмен с 1C по TCP/IP между различными устройствами 15

Статья Программист Нет файла v8 Бесплатно (free) Разработка внешних компонент

Часто нужно обмениваться данными с клиентом 1С из различных устройств, между клиентами 1С, а также при виртуализации между разными ОС на компьютере. Это кроссплатформенная ВК, позволяющая обмениваться сообщениями по TCP/IP между различными устройствами по определенному протоколу.

28.09.2016    17645    Serginio    8       

Net Core. Динамическая компиляция класса обертки для получения событий .Net объекта в 1С 8

Статья Программист Нет файла v8 Бесплатно (free) Разработка внешних компонент

Часто нужно использовать события объектов .Net. Например событие от COM порта, поступление сообщений по WhatsAp, сообщение об изменение в директории итд. Напрямую этого сделать нельзя, но можно сделать класс обертку и через него получать ВнешнееСобытие

14.09.2016    13527    Serginio    1       

.Net Core, 1C, динамическая компиляция, Scripting API 10

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования Разработка внешних компонент

Очень часто приходится использовать динамический код в 1С, используя Выполнить или Вычислить. Аналогичная задача и для использования скриптов на .Net. Я постарался показать, как можно скрестить ежа с ужом и получить удобный код. В этой статье много вражеского кода для чистого одноэсника, но все когда-то бывает впервые.

07.09.2016    15836    Serginio    7       

1С, Linux, Excel, Word, OpenXML, ADO, Net Core 31

Инструменты и обработки Программист Архив с данными v8 Бесплатно (free) Разработка внешних компонент

В данной статье показаны примеры кроссплатформенной работы с файлами Excel и Word (xlsx,docx) с помощью библиотеки OpenXML и Net Core

22.08.2016    17286    51    Serginio    14       

Асинхронное программирование в 1С через использование классов .Net из Native ВК 14

Статья Программист Нет файла v8 Бесплатно (free) Разработка внешних компонент

Это продолжение статьи Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux II http://infostart.ru/public/541518/ В этой статье покажу, как можно асинхронно вызывать асинхронные методы и вызывать ВнешнееСобытие в 1С из сборки .Net

09.08.2016    14658    Serginio    3       

Регистры сведений 1С. Как это устроено. 729

Статья Программист Нет файла v8 Бесплатно (free) Математика и алгоритмы

Основная идея публикации - собрать в одном месте информацию о внутреннем устройстве такой абстрактной сущности, как "Регистр сведений 1С" и ответить на ряд вопросов: Что происходит при записи регистра в различных режимах? Что такое на самом деле "СрезПервых" и "СрезПоследних"? Как оптимально выбрать структуру регистра? Это та информация, владея которой, начинаешь лучше понимать как это работает и как правильно использовать регистры сведений.

05.08.2016    151048    Sergey.Noskov    155       

Переводим расширения на 8.3.8. Памятка. 79

Статья Программист Нет файла v8 Россия Бесплатно (free) Практика программирования Математика и алгоритмы

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

29.07.2016    39710    mrXoxot    12       

Опыт практического применения методики BDD на 1С. Написание сценариев 121

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования Математика и алгоритмы

Эта статья открывает цикл публикаций, в которых я хочу поделиться опытом использования методики BDD при разработке на 1С. В этой статье речь пойдёт о написании сценариев.

03.07.2016    20335    oleynik.dv    132       

Заметки про запросы. Последовательность. 110

Статья Программист Нет файла v8 Windows Бесплатно (free) Математика и алгоритмы Практика программирования

Рассуждения, основанные на контрпримерах. Определяем последовательность операций с помощью одной только консоли запросов. Версия 2.

27.05.2016    29630    vasilev2015    31       

.Net в 1С. Асинхронные HTTP запросы, отправка Post нескольких файлов multipart/form-data, сжатие трафика с использованием gzip, deflate, удобный парсинг сайтов и т.д. 37

Статья Программист Нет файла v7.7 v8 Windows Бесплатно (free) Практика программирования Разработка внешних компонент WEB

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

09.03.2016    25955    Serginio    22       

Быстрое создание Внешних Компонент на C#. Примеры использования Глобального Контекста, IAsyncEvent, IExtWndsSupport, WinForms и WPF 42

Статья Программист Нет файла v8 Windows Бесплатно (free) Практика программирования Разработка внешних компонент

В большинстве случаев хватает и обычного COM объекта, учитывая, что в 8.х можно использовать события. Но иногда нужно использовать Глобальный Контекст для вызова глобальных функций, таких как Сообщить, NewObject и т.д. Кроме того, для использования форм нужен дескриптор окна 1С. Это продолжение статей Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент. http://infostart.ru/public/238584/ Там же лежат и исходники .NET(C#) для 1С. Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия http://infostart.ru/public/417830/ 1C Messenger для отправки сообщений, файлов и обмена данными между пользователями 1С, вэб страницы, мобильными приложениями а ля Skype, WhatsApp http://infostart.ru/public/434771/ Использование классов .Net в 1С для новичков http://infostart.ru/public/448668/

15.02.2016    24683    Serginio    13       

Оптимизация планирования доставки грузов. Алгоритм кластеризации k-means (метод K-средних). 26

Статья Программист Нет файла v8 УТ10 УПП1 Windows Бесплатно (free) Математика и алгоритмы

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

10 стартмани

09.02.2016    26526    mi1man    4       

Подсветка синтаксиса 1С в текстовых редакторах Atom, Sublime Text, VS Code 101

Статья Системный администратор Программист Нет файла v8 1cv8.cf Бесплатно (free) Инструментарий разработчика Разработка внешних компонент

Пакеты, добавляющие поддержку синтаксиса языка 1С:Предприятие 8 в текстовые редакторы Atom, Sublime Text и VS Code. И не только.

02.02.2016    23209    nixel    38       

Использование классов .Net в 1С для новичков 147

Статья Программист Нет файла v7.7 v8 Windows Бесплатно (free) Практика программирования Разработка внешних компонент Универсальные функции

Руководство для новичков. Написав статью http://infostart.ru/public/238584/, я понял, что многие не понимают того, что написано. Поэтому в этой статье постараюсь более подробно остановиться на азах и без кода на вражеском языке (C#)

27.01.2016    63758    Serginio    104       

Контур.EDI изнутри, или история командной разработки тиражного продукта на 1С 174

Статья Программист Нет файла v8 Россия УУ Windows Оптовая торговля Бесплатно (free) Интеграция Практика программирования Математика и алгоритмы

“Система - больше, чем просто совокупность ее элементов”; “Несколько разработчиков - это еще не команда разработки”. Расскажу, как мы прочувствовали эти очевидные утверждения на своей шкуре.

17.11.2015    36044    skif47    88       

Порядок записи движений регистров при проведении документа 95

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования Математика и алгоритмы

Когда-то была программа 1С седьмой версии, и все программисты знали: если нужно проанализировать и/или исправить движения документа - смотри модуль документа, процедура ОбработкаПроведения(). В 1С 8 все гораздо сложнее. Кроме модуля проведения есть еще подписки на события, а также движения документа может "создавать" не сам документ. Эта статья о том, как происходит проведение и в какой момент записываются движения документа по регистрам.

13.11.2015    80528    triton_tver    8       

Три способа получить дерево элементов иерархического справочника 52

Статья Программист Нет файла v8 Бесплатно (free) Математика и алгоритмы

Рассматривается применимость и недостатки следующих способов получения дерева 1) Запрос с использованием итогов по иерархии 2) Формирование дерева обходом выборки с упорядочиванием по иерархии 3) Формирование иерархии по списку элементов транзитивным замыканием

11.11.2015    63125    32ops    9