# 透過 Gemini 程式庫追求動態

Ted Neward

``````var myCar = new Object();
myCar.make = "Ford";
myCar.model = "Mustang";
myCar.year = 1969;
myCar.makeSounds = function () {
console.log("Vroom!
Vroom!")
}
``````

## 快速入門

``````[TestMethod]
public void CanISetAndGetProperties()
{
dynamic person = new Gemini(
new { FirstName = "Ted", LastName = "Neward" });
Assert.AreEqual(person.FirstName, "Ted");
Assert.AreEqual(person.LastName, "Neward");
}
``````

``````[TestMethod]
public void CanISetAndGetPropertiesDifferentWays()
{
dynamic person = new Gemini(
new { FirstName = "Ted", LastName = "Neward" });
Assert.AreEqual(person.FirstName, "Ted");
Assert.AreEqual(person.LastName, "Neward");
person = new Gemini();
person.SetMember("FirstName", "Ted");
person.SetMember("LastName", "Neward");
Assert.AreEqual(person.GetMember("FirstName"), "Ted");
Assert.AreEqual(person.GetMember("LastName"), "Neward");
}
``````

``````[TestMethod]
public void MakeNoise()
{
dynamic person =
new Gemini(new { FirstName = "Ted", LastName = "Neward" });
person.MakeNoise =
new DynamicFunction(() => "Uh, is this thing on?");
person.Greet =
new DynamicFunctionWithParam(name => "Howdy, " + name);
Assert.IsTrue(person.MakeNoise().Contains("this thing"));
}
``````

``````string SayHello(dynamic thing)
{
return String.Format("Hello, {0}, you are {1} years old!",
thing.FirstName, thing.Age);
}
[TestMethod]
public void DemonstrateStructuralTyping()
{
dynamic person = new Gemini(
new { FirstName = "Ted", LastName =
"Neward", Age = 42 });
string message = SayHello(person);
Assert.AreEqual("Hello, Ted, you are 42 years old!",
message);
dynamic pet = new Gemini(
new { FirstName = "Scooter", Age = 3, Hunter = true });
string otherMessage = SayHello(pet);
Assert.AreEqual("Hello, Scooter, you are 3 years old!",
otherMessage);
}
``````

## 審訊

``````int Hunt(dynamic thing)
{
return thing.Hunt();
}
``````

``````[TestMethod]
public void AHuntingWeWillGo()
{
dynamic pet = new Gemini(
new
{
FirstName = "Scooter",
Age = 3,
Hunter = true,
Hunt = new DynamicFunction(() => new Random().Next(4))
});
int hunted = Hunt(pet);
Assert.IsTrue(hunted >= 0 && hunted < 4);
// ...
}
``````

``````[TestMethod]
public void AHuntingWeWillGo()
{
// ...
dynamic person = new Gemini(
new
{
FirstName = "Ted",
LastName = "Neward",
Age = 42
});
hunted = Hunt(person);
Assert.IsTrue(hunted >= 0 && hunted < 4);
}
``````

``````int Hunt(dynamic thing)
{
if (thing.RespondsTo("Hunt"))
return thing.Hunt();
else
// If you don't know how to hunt, you probably can't catch anything.
return 0;
}
``````

## Prototype

``````public class Cat : Gemini
{
public Cat() : base() { }
public Cat(string name) : base(new { FirstName = name }) { }
}
``````

## 擴充類別

``````string Htmlize(string incoming)
{
string temp = incoming;
temp = temp.Replace("&", "&amp;");
temp = temp.Replace("<", "&lt;");
temp = temp.Replace(">", "&gt;");
return temp;
}
``````

``````[TestMethod]
public void HtmlizeKittyNames()
{
Gemini.Extend<Cat>(cat =>
{
cat.MakeNoise = new DynamicFunction(() => "Meow");
cat.Hunt = new DynamicFunction(() => new Random().Next(4));
var members =
(cat.HashOfProperties() as IDictionary<string, object>).ToList();
members.ForEach(keyValuePair =>
{
cat.SetMember(keyValuePair.Key + "Html",
new DynamicFunction( () =>
Htmlize(cat.GetMember(keyValuePair.Key))));
});
});
dynamic scooter = new Cat("Sco<tag>oter");
Assert.AreEqual("Sco<tag>oter", scooter.FirstName);
Assert.AreEqual("Sco&lt;tag&gt;oter", scooter.FirstNameHtml());
}
``````

## 持久性和更多

Ted Neward 是校長與 Neward & 同夥 LLC。他已寫了 100 多個文章和創作和合著十多本書，包括"專業 F # 2.0"（Wrox 2010)。他是 F # MVP 和注意到JAVA專家，並在世界各地的JAVA和.NET 會議上講話。他諮詢和週期性導師 — — 達到他在 ted@tedneward.comTed.Neward@neudesic.com 如果你感興趣了他來與您的團隊工作。在他的博客 blogs.tedneward.com 可以跟隨在 Twitter 上和 twitter.com/tedneward