Tengo el siguiente código que crea un objeto dinámico que está asignado a la variable smtpClient.¿Por qué una Microsoft.CSharp.RuntimeBinder.RuntimeBinderException si el método invocado está allí?
public class TranferManager
{
public void Tranfer(Account from, Account to, Money amount)
{
// Perform the required actions
var smtpClient = New.SmtpClient();
smtpClient.Send("[email protected]", "from.Email", "Tranfer", "?");
// In the previous line I get a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
// with the description = "'object' does not contain a definition for 'Send'"
}
}
public static class New
{
public static dynamic SmtpClient(params object[] parameters)
{
return typeof(SmtpClient).New(parameters);
}
}
public static class CreationExtensions
{
private static Dictionary<Type, Func<object, dynamic>> builders =
new Dictionary<Type, Func<object, dynamic>>();
public static dynamic New(this Type type, params object[] parameters)
{
if(builders.ContainsKey(type))
return builders[type](parameters);
return Activator.CreateInstance(type, parameters);
}
public static void RegisterBuilder(this Type type, Func<object, dynamic> builder)
{
builders.Add(type, builder);
}
}
Para probar que estoy usando el UT (abajo):
[TestMethod()]
public void TranferTest()
{
typeof(SmtpClient).RegisterBuilder(p =>
new
{
Send = new Action<string, string, string, string>(
(from, to, subject, body) => { })
}
);
var tm = new TranferManager();
tm.Tranfer(new Account(), new Account(), new Money());
// Assert
}
Cuando, utilizando las ventanas inmediatas, pido para el tipo SMTPClient me sale:
smtpClient.GetType()
{<>f__AnonymousType0`1[System.Action`4[System.String,System.String,System.String,System.String]]}
Y cuando pregunto por sus miembros me aparece:
smtpClient.GetType().GetMembers()
{System.Reflection.MemberInfo[7]}
[0]: {System.Action`4[System.String,System.String,System.String,System.String] get_Send()}
[1]: {System.String ToString()}
[2]: {Boolean Equals(System.Object)}
[3]: {Int32 GetHashCode()}
[4]: {System.Type GetType()}
[5]: {Void .ctor(System.Action`4[System.String,System.String,System.String,System.String])}
[6]: {System.Action`4[System.String,System.String,System.String,System.String] Send}
Entonces, mi pregunta es: ¿por qué recibo esa excepción?
uhmm ... copiar todo el código en una Aplicación de consola (y el contenido de su método de prueba en mi método "principal") no arroja ninguna excepción para mí. Supongo que tu TestMethod está en una dll diferente. Tal vez haya un problema con la versión de .NET a la que se dirige en el dll o sus referencias. –
Lo mismo aquí. Cuando ejecuto su código (habiendo proporcionado definiciones adecuadas de Cuenta, Dinero, etc.) no obtengo ninguna excepción. ¿Puede proporcionar un pequeño programa que * realmente compila, ejecuta y demuestra el problema? * –
Tiene razón, copiando el código de prueba en un método "Principal()" de una aplicación de consola que funciona. Ahora puedo ver el problema: el tipo anónimo (creado en el dll de prueba) no es visible desde su dll. – lontivero