Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия, а так же генерация модулей на C# и 1С для подключения к событиям. Использование DynamicMethod и ILGenerator. Представлены примеры для использовании событий System.IO.FileSystemWatcher (Ожидает уведомления файловой системы об изменениях и инициирует события при изменениях каталога или файла в каталоге.) и SerialPort (обработка сканера штрих кода подключенного к COM порту). Обертка позволяет использовать классы .Net только на языке 1С.Реализация 1C Messenger описанного здесь http://catalog.mista.ru/public/434771/
Эта статья является дополнением разработки Использование сборок .NET в 1С 7.x b 8.x находящейся здесь http://catalog.mista.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 interfaceIВрапперДля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;
privateObject 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(newWindowsFormsSynchronizationContext());
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");
};
}
publicstaticobjectСоздатьОбъект(object AutoWrap, System.IO.FileSystemWatcher РеальныйОбъект)
{
returnnewВрапперДля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)]
publicinterfaceIAsyncEvent
{
void SetEventBufferDepth(int lDepth);
void GetEventBufferDepth(refint plDepth);
void ExternalEvent(string bstrSource, string bstrMessage, string bstrData);
void CleanBuffer();
}
publicclassВрапперДляSystem_IO_FileSystemWatcher77
{
System.IO.FileSystemWatcher РеальныйОбъект;
publicobject Changed;
publicobject Created;
publicobject Deleted;
publicobject Error;
publicobject Renamed;
publicobject Disposed;
dynamic AutoWrap;
privateSynchronizationContext Sc;
IAsyncEventСобытиеДля1С;
privateObject thisLock = newObject();
publicobjectПоследняяОшибка;
publicВрапперДляSystem_IO_FileSystemWatcher77(object AutoWrap, ObjectГлобальныйКонтекст, System.IO.FileSystemWatcher РеальныйОбъект)
{
СобытиеДля1С = ГлобальныйКонтекстasIAsyncEvent;
if (SynchronizationContext.Current == null)
SynchronizationContext.SetSynchronizationContext(newWindowsFormsSynchronizationContext());
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)
{
}
}
}
});
}
publicstaticobjectСоздатьОбъект(object AutoWrap, ObjectГлобальныйКонтекст, System.IO.FileSystemWatcher РеальныйОбъект)
{
returnnewВрапперДля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" Тогда
Шаблон("[" + ИмяСобытия+ "()]");
КонецЕсли;
КонецПроцедуры // ОбработкаВнешнегоСобытия
Динамическая компиляция происходит следующим образом
publicclassКомВраперДляСобытий<T>
{
privatestaticMethodInfo cоздательОбертки = null;
privatestaticMethodInfo cоздательОбертки77 = null;
staticCompilerResultsСкомпилироватьОбертку(stringстрокаКласса,stringИмяКласса)
{
boolЭтоСборкаГак = typeof(T).Assembly.GlobalAssemblyCache;
stringПуть = Path.GetDirectoryName(typeof(T).Assembly.Location);
string OutputAssembly = Path.Combine(Путь, ИмяКласса) + ".dll";
var compiler = newCSharpCodeProvider();
var parameters = newCompilerParameters();
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;
}
publicstaticMethodInfoСоздательОбертки { get {
if (cоздательОбертки==null)
{
TypeтипРеальногоОбъекта = typeof(T);
stringТипСтрРеальногоОбъекта = типРеальногоОбъекта.FullName;
varИмяКласса = "ВрапперДля" + ТипСтрРеальногоОбъекта.Replace(".", "_").Replace("+", "_");
string строкаКласса = ДляСозданияМодуляВрапера.СоздатьОписания(типРеальногоОбъекта);
var res = СкомпилироватьОбертку(строкаКласса,ИмяКласса);
Typeтип = res.CompiledAssembly.GetType(ИмяКласса);
MethodInfo mi = тип.GetMethod("СоздатьОбъект", newType[]{typeof(object),типРеальногоОбъекта });
cоздательОбертки = mi;
}
return cоздательОбертки;
} }
publicstaticMethodInfoСоздательОбертки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("СоздатьОбъект", newType[] { 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(newType[] { тип });
// Nowнаходим свойство и получаем его значение
PropertyInfo pi = constructed.GetProperty(ИмяСвойства);
MethodInfoфункция = (MethodInfo)pi.GetValue(null, null);
returnфункция;
}
publicobjectСоздатьОберткуДляСобытий(objectобъект)
{
object РеальныйОбъект = AutoWrap.ПолучитьРеальныйОбъект(объект);
var функция = ПолучитьMethodInfoОберткиСобытий("СоздательОбертки", РеальныйОбъект);
object обертка = функция.Invoke(null,newobject[] { this,РеальныйОбъект });
// Возвращаем реальный объект, так как он является COM объектом
return обертка;
}
publicobject СоздатьОберткуДляСобытий77(object объект, object ГлобальныйКонтекст)
{
object РеальныйОбъект = AutoWrap.ПолучитьРеальныйОбъект(объект);
var функция = ПолучитьMethodInfoОберткиСобытий("СоздательОбертки77", РеальныйОбъект);
object обертка = функция.Invoke(null, newobject[] {ГлобальныйКонтекст,РеальныйОбъект });
// Оборачиваем обертку событий в AutoWrap для использования в 1С как объекта автоматизации
returnAutoWrap.ОбернутьОбъект(обертка);
}
Кроме того, можно использовать DynamicMethod. В отличие от динамической компиляции сборки, определяет и представляет динамический метод, который может быть скомпилирован, выполнен и удален.Удаленные методы доступны для сборки мусора.
Так, в 1С нет операторов для битовых операций. Для работы с FileSystemWatcher
Нам нужно определить события которые мы хотим отслеживать. На C# это выглядит так.
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
Создадим функцию в C# проекте
publicstaticNotifyFilters 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
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)
Также рекомендую вводную серию статей — тынц.
Также рекомендую вводную серию статей — тынц.
Большая благодарность Sinix
publicMethodBuilder BuildMethodOR(TypeBuildertype)
{
// 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;
Функция ПолучитьМетод()
//"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);
КонецПроцедуры
http://daveaglick.com/posts/compiler-platform-scripting
Процедура DataReceived(Данные)
sp1 = Данные.sender;
ШтрихКод= sp1.ReadExisting();
Компорт= sp1.PortName;
Сообщить(СтрШаблон("ШК=%1 Порт=%2",ШтрихКод,Компорт));
КонецПроцедуры
Комментариев нет:
Отправить комментарий