Interoperability
The dynamic
Type
Advantages
Interoperability with dynamic languages and frameworks
dynamic d = "Test";
Console.WriteLine(d); // Output: Test
d = d.ToUpper();
Console.WriteLine(d); // Output: TEST
d = 3; // d changes its runtime type to int
Console.WriteLine(d); // Output: 3
d += 7;
Console.WriteLine(d); // Output: 10
Disadvantages
Deactivates type checking and IntelliSense, Everything compiles:
dynamic speaker = new NonSenseTalker();
speaker.HelloWorld();
speaker.Im().Just().Demonstrating().This().Feature();
speaker.GoodBye();
Run python in C
static dynamic Calculate(string expression) {
var engine = Python.CreateEngine();
return engine.Execute(expression);
/*To execute Script
engine.Execute("import pythonDemo\n pythonDemo.factorial(1000)");
*/
}
static void Main(string[] args) {
dynamic result = Calculate("2 * 3");
Console.WriteLine("result : {0}", result);
}
ExpandoObject
ExpandoObjects implements dynamic properties
dynamic o = new ExpandoObject();
o.Test = 123;
o.Foo = "hallo";
o.Bar = new object();
o.F = (Action)(() => Console.WriteLine("Action done"));
o.F()
Console.WriteLine(o.Foo);
Custom Dynamic Types
public class World : DynamicObject
{
private Cities _cities;
public World(Cities cities)
{
_cities = cities;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = _cities.CityList.FirstOrDefault(city => city.Name == binder.Name)
?? (object) $"The city \"{binder.Name}\" does not exist!";
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object? args)
{
City city = null;
try
{
city = _cities[binder.Name];
}
catch (Exception e)
{
throw new InvalidOperationException($"The city \"{binder.Name}\" does not exist!");
}
try
{
var inputs = (args as string).Split(':');
switch (inputs[0])
{
case "Population":
city.Population = Convert.ToInt32(inputs[1]);
break;
case "Latitude":
city.Location.Latitude = Convert.ToDouble(inputs[1]);
break;
case "Longitude":
city.Location.Longitude = Convert.ToDouble(inputs[1]);
break;
default: throw new ArgumentException("Invalid property assigned");
}
}
catch (Exception e)
{
throw new ArgumentException("Invalid property value passed");
}
return true;
}
}
public virtual bool TryInvokeMember(InvokeBinder binder, Object[] args , out Object result) so you can call dynamic methods like duck.Quack();
P/Invoke
Allows you to execute unmanaged/native code for example you can call a C++ DLL.
- Locates the DLL containing the function.
- Loads the DLL into memory.
- Locates the address of the function in memory and pushes its arguments onto the stack, marshaling data as required.
- Transfers control to the unmanaged function
class Test {
[DllImport("user32.dll)"]
static extern int MessageBox(uint hWnd, string text, string caption, uint type);
static void Main() {
MessageBox(0, "Calling native code isn't that cool?", "", 1,
}
}
COM interoperability
COM stands for "Component Object Model". Mostly used to control Microsoft products, windows word etc. So for example you can build plugins.
using Word = Microsoft.Office.Interop.Word
var word = new Word.Application();
word.Documents.Add();
word.ActiveDocument.SaveAs("test.doc");