Тезисы
??? Тип dynamic можно использовать для определения аргументов типов обобщенных классов (ссылочный тип), структур (значимый тип), интерфейсов, делегатов или методов. Когда вы это делаете, компилятор конвертирует тип dynamic в Object и применяет DynamicAttribute к различным частям метаданных, где это необходимо. Обратите внимание, что обобщенный код, который вы используете, уже скомпилирован в соответствии с типом Object, и динамическая отправка не осуществляется, поскольку компилятор не производит код полезной нагрузки в обобщенном коде ???
Что динамическая отправка не осуществляется???
Компилятор считает что это типа object , генерирует код полезной нагрузки, который в run-time сможет определить какой метод вызвать:
dynamic q = "213";
q + "123"
или
dynamic q = 123
q + 123
Будет вызван либо метод сложения либо для строк, либо для целых чисел Если объект используется в foreach то компилятор пытается привести его к IEnumerable, если в using, то происходит cast к IDisposable Привязку методов и полей во время выполнения осуществляет run-time binder, разные языки реализуют своих компоновщиков для привязки в run-time, может показаться что постоянные вызовы динамического метода это очень непроизводительно, потому что binder должен каждый раз разрешать тип объекта, но все же проведены определенные меры, например, весь код полезной назрузки выполненный для привязки будет помещен в анонимную сборку динамических методов, для того, чтобы в следующий раз, при вызове этого кода с тем же типом(который скрывается за dynamic), не пришлось генерировать его снова еще раз
В чем отличается вызов динамического метода на типе который реализует IDynamicMetaObjectProvider и не реализует его
Если происходит вызов на типе реализующем IDynamicMetaObjectProvider, то в run-time вызвав GetMetaObject(), можно получить DynamicMethodObject, который может обработать все вызовы методов и привязки для этого объекта Если же нет, то для привязки методов будет использоваться рефлексия Например в C# опреден ExpandoObject, который реализует IDynamicMetaProvider
Можно унаследовать свой тип от DynamicObject, в нем доступны виртуальные методы привязки, которые можно переопределить, например, TrySetMember, который будет вызываться при таких обращенияз:
public class TestDynamicObject : DynamicObject
{
public override bool TrySetMember(SetMemberBinder binder, object value)
{
Console.WriteLine($"name:{binder.Name},value:{value}");
return base.TrySetMember(binder, value);
}
}
...
public void Method()
{
dynamic q = new TestDynamicObject();
q.TestField = "testField";
// name: TestField, value:"testField"
}
Загрузить в домен приложения Microsoft.CSharp.dll, также вместе с ней будут загружены System.dll и System.Core.dll