Если у вас есть контроль над всеми типами объектов, которые вы будете использовать динамически, другой вариант будет заключаться в том, чтобы заставить их наследовать от подкласса класса DynamicObject
, который настроен так, чтобы не вызывать сбой, когда метод не существовать вызывается:
Быстрая и грязная версия будет выглядеть так:
public class DynamicAnimal : DynamicObject
{
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
bool success = base.TryInvokeMember(binder, args, out result);
// If the method didn't exist, ensure the result is null
if (!success) result = null;
// Always return true to avoid Exceptions being raised
return true;
}
}
Затем вы можете сделать следующее:
public class Duck : DynamicAnimal
{
public string Quack()
{
return "QUACK!";
}
}
public class Cow : DynamicAnimal
{
public string Moo()
{
return "Mooooo!";
}
}
class Program
{
static void Main(string[] args)
{
var duck = new Duck();
var cow = new Cow();
Console.WriteLine("Can a duck quack?");
Console.WriteLine(DoQuack(duck));
Console.WriteLine("Can a cow quack?");
Console.WriteLine(DoQuack(cow));
Console.ReadKey();
}
public static string DoQuack(dynamic animal)
{
string result = animal.Quack();
return result ?? "... silence ...";
}
}
И ваш вывод будет:
Can a duck quack?
QUACK!
Can a cow quack?
... silence ...
Редактировать: Я должен отметить, что это вершина айсберга, если вы можете использовать этот подход и опираться на DynamicObject
. Вы можете написать такие методы, как bool HasMember(string memberName)
, если хотите.