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

21.12.16

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

Динамическая компиляция класса обертки для использования .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 находящейся здесь //infostart.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используя программы //infostart.ru/public/14587/ .

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

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

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

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

.Net C# event DynamicMethod

См. также

Разработка внешних компонент WEB-интеграция Программист Платформа 1С v7.7 Конфигурации 1cv7 Платные (руб)

Компонента HttpSrv7 позволяет создавать веб-сервисы в среде 1С 7.7 и даже, используя файлы HTML, несложные веб-сайты. С помощью нее можно обеспечить доступ к данным 1С 7.7 из браузера. Дополнительно используя компоненту HTTP_Async или синхронный клиент HTTP для 1С 7.7 (публикация № 1152364) можно наладить обмен данными между удаленными информационными базами. С помощью компоненты HTTP_Async можно сначала послать несколько запросов к сайтам, веб-сервисам (в т.ч. к HttpSrv7), а затем обрабатывать данные по мере их поступления. Компонента GISMT в дополнение к HTTP_Async имеет функцию цифровой подписи и, таким образом, имеет все возможности для работы с API ГИС МТ "Честный знак" непосредственно из среды 1С 7.7.

2000 руб.

27.05.2022    8791    23    17    

34

Разработка внешних компонент Системный администратор Программист Платформа 1С v7.7 Платформа 1С v8.3 Платформа 1C v8.2 Платформа 1С v8.1 Россия Платные (руб)

Аддон "Структура Обмена" (ExchangeStruc) - это компонента, которая обеспечивает доступ к разделяемым процессом структурам, аналогичным структурам 1С. Обеспечивает прозрачную передачу данных примитивных типов, в том числе Двоичных данных, в режиме Реального времени между разными контекстами (формами) или потоками одного процесса. В перспективе функционал будет расширен для обмена между процессами, даже разных версий платформ. Совместим с версиями Windows рабочих станций и серверов, с платформами 1С разных версий и релизов в режиме Native начиная с 8.2, и в режиме COM начиная с версий 7.7. По скорости чтения и записи лишь немногим уступает стандартной структуре 1С. НОВОЕ: Добавлен функционал регистрации компоненты COM в качестве OLE Auto (COMОбъект) для поддержки её работы в серверах старых версий 1С: 8.0 и 8.1, где работа с компонентами исключена. Теперь можно коммуникацию с Фоновыми заданиями на этих версиях проводить.

7200 руб.

19.04.2023    5242    1    0    

3

Разработка внешних компонент Программист Платформа 1С v7.7 Платные (руб)

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

1200 руб.

02.12.2021    6216    2    19    

4

Разработка внешних компонент Оптовая торговля Программист Пользователь Платформа 1С v7.7 Конфигурации 1cv7 Управленческий учет Платные (руб)

Расширяем уровень взаимодействия c пользователем с помощью новых возможностей - форма для ввода количества для перемещений и форма ввода количества с упаковками и штуками.

1200 руб.

08.09.2021    7573    0    2    

1

Разработка внешних компонент Файловый обмен (TXT, XML, DBF), FTP Программист Платформа 1С v7.7 Конфигурации 1cv7 Абонемент ($m)

Эта внешняя компонента Base64.dll предназначена для платформы 1С версии 7.7. Используется для преобразования файлов из/в кодировку Base64 из встроенного языка 1С Предприятие. Компонента тестировалась на базе конфигурации Бухгалтерский учет для Казахстана, редакции 7.70.257.

10 стартмани

06.04.2021    9956    14    softmaker    13    

5

Разработка внешних компонент Защита ПО и шифрование Программист Платформа 1С v7.7 Абонемент ($m)

Цифровые подписи, шифрование, просмотр сертификатов ключей ЭЦП, работа с различными криптопровайдерами (в т.ч. КриптоПРО ГОСТ 2012) в 1С 7.7.

1 стартмани

08.06.2020    9393    28    mdbruyfn    10    

9

Разработка внешних компонент Программист Платформа 1С v7.7 Абонемент ($m)

Обмен сообщениями и небольшими файлами по протоколу UDP с 1С и внешними приложениями в локальной сети или сети VPN.

1 стартмани

23.05.2020    7563    7    mdbruyfn    0    

6

Журнал регистрации Программист Бесплатно (free)

Работа с журналом регистрации нестандартными средствами. А также немного про использование платформы .NET в экосистеме 1С.

12.05.2020    20065    Infostart    32    

93
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. shakmaev 347 13.11.15 11:45 Сейчас в теме
Беда с оформлением статьи, и куда только смотрят модераторы?
гвость; +1 Ответить
2. Serginio 941 13.11.15 12:04 Сейчас в теме
(1) А по существу? Просто править текст очень тяжело.
3. cool.vlad4 2 13.11.15 12:20 Сейчас в теме
(2) статья полезная. только (1) прав. код c# можно было на pastebin разместить, а здесь ссылку оставить. (часть кода ис распарсил в ссылки )
5. Serginio 941 13.11.15 13:03 Сейчас в теме
(3) Спасибо. Учту и попробую
(4) Спасибо.
4. gortol 202 13.11.15 12:29 Сейчас в теме
зато открывает возможности описания собственных событий, очень полезная информация, мне не хватило информации из интернета как раз для формирования собственных событий и передать их в 1с...
6. ivanov660 4578 15.11.15 12:44 Сейчас в теме
Довольно забавно получается - надо писать 1Сом Сишарп.
На мой взгляд:
1. Надо не забывать о правах пользователя под которым собирается и компилируется код.
2. Необходимо не забывать про обработку ошибок при динамической компиляции.
3. Про версии .net при которых возможно использование данных возможностей - где-то от 3.5+ и выше.
4. Можно было просто передать текстовый кусок кода (*.cs) и скомпилировать его на лету.
8. Serginio 941 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 35 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 253 15.11.15 13:06 Сейчас в теме
То есть использование .Net в 1С станет достаточно простым.

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

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

Все остальное, это рассказ о том как формируется реальный код. То есть, для тех кому это интересно и использовать сгенеренный код для дальнейшей модификации или как использовать обвязку нетовских свойств для использования через ДобавитьОбработчик или ОбработкаВнешнегоСобытия. Думаю многим это будет полезным. За оформление прошу прощения. Спешил, да и дизайнерские способности у меня невысокие
10. cool.vlad4 2 15.11.15 23:13 Сейчас в теме
(9) да дизайнерские способности ни причем. я например вообще не хочу публиковать статьи на ис, поскольку публикация это боль (у меня процессор так грузился как не зная что, но может с тех пор ситуация изменилась) , ну и форматирование там так себе. насчет статьи, я напимер в теме. (некоторые свои вк, кстати публиковал, опять же по причине движка ис в комментах). но имхо с com есть некоторый геморрой при деплое. например, мне были бы интереснее вещи касательно обмена данных, генерации всяких dto между приложением на C# (какой-нибудь сервис) и 1С. тут нет никакой магии , но просто может есть наработки . и еще была бы интересна генерация именно 1С кода. и некоторый анализатор его . вот с шарпом как раз таки проблем тут нет. (учитывая что Roslyn уже есть)
11. Serginio 941 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 2 16.11.15 00:03 Сейчас в теме
(11) регистрация это и есть проблема. админам это доверять не всегда хочется. а вручную самому во-первых нет смысла этим заниматься, а во-вторых не всегда есть соотвествующие права на ветки реестра.
13. Serginio 941 16.11.15 00:06 Сейчас в теме
(12) Так зарегистрировать нужно только NetObjectToIDispatch45. И будет открыт доступ ко всем Net овским классам, где регистрация не нужна
14. cool.vlad4 2 16.11.15 00:15 Сейчас в теме
(13) это то понятно. (аналогично как и у Elisy своя ВК или у ObjectFerm авторство не помню чье). только код будет specific, поскольку в некоторых конторах есть админы , которые просто откажутся что-то регистрировать, то что по их мнению доверия не заслуживает. и получится две версии кода, одна с ВК, другая без ВК и головная боль.
23. avz_1C 10 16.02.16 12:38 Сейчас в теме
(7) delete,

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

Очень грамотно пишете, читаю с удовольствием!
15. Serginio 941 16.11.15 00:20 Сейчас в теме
Использовать COM это необязательно регистрация. Можно сделать ВК (а они есть) которя будет грузить DLL и по гуиду доставать нужный IDispatch. Пример использования кстати есть в http://infostart.ru/public/238584/
16. Aphanas 92 17.11.15 19:21 Сейчас в теме
Други, простите великодушно, тут, видимо не для средних умов. Интересуюсь темой подписки на события через "ДобавитьОбработчик". Не могу врубиться, что делает эта разработка? Объясните кто-нибудь на простом языке. Я вижу кучу кода на C#, но куда всё это надо толкать, я так и не понял. И как это потом к "ДобавитьОбработчик" прикручивать?
17. Serginio 941 17.11.15 23:28 Сейчас в теме
(16) Это надо скачать http://infostart.ru/public/238584/ там есть обработки с генерацией 1С кода для подключения события.
И смотри пример с SerialPort для считывания Штрих-Кода.
Куча кода на C# объясняет только одну строку ОберткаСобытий=врап.СоздатьОберткуДляСобытий(объект);
18. Serginio 941 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 160 21.12.15 09:48 Сейчас в теме
я не в теме.
и мне ничего не понятно.
20. Serginio 941 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 941 21.12.15 11:13 Сейчас в теме
А если убрать C# код то суть всей этой стать состоит в вызове методов

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


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

    ОберткаСобытий= врап.СоздатьОберткуДляСобытий77(ОбертываемыйОбъект,ГлобальныйКонтекст);
22. Serginio 941 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 941 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 941 05.09.16 10:31 Сейчас в теме
Какой то DLL не хватает. Для чистоты эксперимента создай проект встрой туда ссылки на нужные DLL и текст для C# и скомпилируй сборку и её используй для подключения событий
29. TeMochkiN 05.09.16 11:03 Сейчас в теме
(27) у меня получилось, но только после того, как я все зависимые сборки загрузил с помощью врап.ЗагрузитьСборку(ПутьСборки)
30. Serginio 941 05.09.16 13:34 Сейчас в теме
(29) Обычно когда загружается основная сборка, она грузит и все от которых зависит. Спасибо. Буду иметь ввиду.
(28) Большое спасибо!
31. TeMochkiN 05.09.16 13:53 Сейчас в теме
(30) не знаю, может конечно я что-то неправильно делаю, но в любом случае спасибо вам, т.к. обертка событий у меня заработала :)
у вас вообще столько статей интересных, мне их ещё читать и читать)
32. Serginio 941 05.09.16 14:15 Сейчас в теме
(31) Спасибо! и на здоровье.
28. white-mount 05.09.16 10:50 Сейчас в теме
Статья понравилась, добавил в свой в список "избранного". Автору респект.
Код читаю в оригинальной среде, вопросов не возникает.
34. Serginio 941 14.09.16 00:01 Сейчас в теме
Видно еще каких то библиотек не хватает. Для начала попробовать загрузить из .Net приложения.
Возможно нужно поместить в GAC. https://msdn.microsoft.com/ru-ru/library/h4fa028b(v=vs.110).aspx
Я с этим не сталкивался
35. Dionisiy 4 14.05.20 12:16 Сейчас в теме
Отличная работа, много раз обращался, поделюсь своими наработками. В 77 добавляю в таблицу ROT

  public КонструкторКласса()
        {
Guid guid = Marshal.GenerateGuidForType(typeof(КонструкторКласса));
Ole32.RegisterActiveObject(this, ref guid, 0, out m_dwRegister);
}


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

if (m_dwRegister != 0)
            {                

                IBindCtx bc;
                Ole32.CreateBindCtx(0, out bc);

                IRunningObjectTable rot;
                bc.GetRunningObjectTable(out rot);
                rot.Revoke(m_dwRegister);
                m_dwRegister = 0;
            }
Показать


Таким образом, 1С в одном из вызовов Init (всего их три) передает заполненный контекст. Сделал клавиатурный драйвер сканера ШК, он создает событие, которое вызывает ExternalEvent ОбработкаВнешнегоСобытия.
36. Serginio 941 14.05.20 19:15 Сейчас в теме
(35) Спасибо! Интересно! И не знал
Оставьте свое сообщение