.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

См. также

HTTP сервер 1С 7.7 + HTTP асинхронный клиент: внешние компоненты для 1С 7.7

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

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

2000 руб.

27.05.2022    7766    19    13    

31

Компонента ExchangeStruc (Структура Обмена). Прямой обмен данными между потоками, сессиями и окнами.

Разработка внешних компонент Платформа 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    4784    1    0    

3

Выбор из большого списка (для 1С 7.7)

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

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

1200 руб.

02.12.2021    5768    2    19    

4

Форма для ввода количества товаров

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

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

1200 руб.

08.09.2021    7384    0    2    

1

Внешняя компонента для преобразования файлов из/в кодировку Base64 в 1С 7.7

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

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

10 стартмани

06.04.2021    9427    14    softmaker    12    

5

Криптография: внешняя компонента для 1С 7.7

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

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

1 стартмани

08.06.2020    9034    27    mdbruyfn    10    

9

Протокол UDP: внешняя компонента для 1С 7.7

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

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

1 стартмани

23.05.2020    7308    5    mdbruyfn    0    

6

Работа с журналом регистрации. Выходим за границы платформы

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

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

12.05.2020    18390    Infostart    32    

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

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

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

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


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

    ОберткаСобытий= врап.СоздатьОберткуДляСобытий77(ОбертываемыйОбъект,ГлобальныйКонтекст);
22. Serginio 938 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 938 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 938 05.09.16 10:31 Сейчас в теме
Какой то DLL не хватает. Для чистоты эксперимента создай проект встрой туда ссылки на нужные DLL и текст для C# и скомпилируй сборку и её используй для подключения событий
29. TeMochkiN 05.09.16 11:03 Сейчас в теме
(27) у меня получилось, но только после того, как я все зависимые сборки загрузил с помощью врап.ЗагрузитьСборку(ПутьСборки)
30. Serginio 938 05.09.16 13:34 Сейчас в теме
(29) Обычно когда загружается основная сборка, она грузит и все от которых зависит. Спасибо. Буду иметь ввиду.
(28) Большое спасибо!
31. TeMochkiN 05.09.16 13:53 Сейчас в теме
(30) не знаю, может конечно я что-то неправильно делаю, но в любом случае спасибо вам, т.к. обертка событий у меня заработала :)
у вас вообще столько статей интересных, мне их ещё читать и читать)
32. Serginio 938 05.09.16 14:15 Сейчас в теме
(31) Спасибо! и на здоровье.
28. white-mount 05.09.16 10:50 Сейчас в теме
Статья понравилась, добавил в свой в список "избранного". Автору респект.
Код читаю в оригинальной среде, вопросов не возникает.
34. Serginio 938 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 938 14.05.20 19:15 Сейчас в теме
(35) Спасибо! Интересно! И не знал
Оставьте свое сообщение