仅在生产环境中抛出 MulticastDelegate 异常
MulticastDelegate exception being thrown only in production environment
我有一个非常奇怪的问题只发生在生产环境中。
异常包含消息
"Delegate to an instance method cannot have null 'this'".
抛异常的方法很简单,搞了半天,所以
问题一定是环境中的一个模糊的依赖关系,或者类似的东西...
我正在使用 ASP.NET Web API,托管在 Azure 中,控制器的操作方法是通过 AJAX 执行的。
这里是抛出异常的代码:
public class BlacklistService : IBlacklistService
{
public bool Verify(string blacklist, string message)
{
if (string.IsNullOrEmpty(blacklist)) return true;
var split = blacklist.ToLower().Split(';'); // exception is thrown here
return !split.Any(message.Contains);
}
}
这里是堆栈跟踪的相关部分:
at System.MulticastDelegate.ThrowNullThisInDelegateToInstance()
at System.MulticastDelegate.CtorClosed(Object target, IntPtr methodPtr)
at MyApp.Business.Services.BlacklistService.Verify(String blacklist, String message)
at MyApp.Business.Services.ContactMessageFactory.GetVerifiedStatus(String mensagem)
at MyApp.Business.Services.ContactMessageFactory.GetMailMessage(ContactForm contactForm)
at MyApp.Business.ContactEmailService.Send(ContactForm contactForm)
有人能找出这个异常的可能原因吗?提前致谢。
消息为空时失败。可以用这个
return !split.Any(part => (message != null && message.Contains(part)));
问题在于 message
实际上是 null
。您可以很容易地重现它:
void Main()
{
Verify("hello", null);
}
public bool Verify(string blacklist, string message)
{
if (string.IsNullOrEmpty(blacklist)) return true;
var split = blacklist.ToLower().Split(';'); // exception is thrown here
return !split.Any(message.Contains);
}
发生的事情是 message.Contains
通过方法组转换传递给 Func<string, bool>
构造函数,它看起来像这样:
Func<string, bool> func = ((string)null).Contains;
return !split.Any(func);
这就是导致 MulticastDelegate
发疯的原因。在生成的IL中也可以看到:
IL_0028: ldftn System.String.Contains
IL_002E: newobj System.Func<System.String,System.Boolean>..ctor
IL_0033: call System.Linq.Enumerable.Any
为了避免这种情况发生,请确保您也对消息进行空检查:
public bool Verify(string blacklist, string message)
{
if (string.IsNullOrEmpty(blacklist)) return true;
if (string.IsNullOrEmpty(message)) return false;
var split = blacklist.ToLower().Split(';'); // exception is thrown here
return !split.Any(message.Contains);
}
具有空 this
的委托是最后使用的方法 string.Contains()
,它使用您的 message
变量作为 this
指针。换句话说,在 message
为空的地方进行了调用。
我有一个非常奇怪的问题只发生在生产环境中。 异常包含消息
"Delegate to an instance method cannot have null 'this'".
抛异常的方法很简单,搞了半天,所以 问题一定是环境中的一个模糊的依赖关系,或者类似的东西...
我正在使用 ASP.NET Web API,托管在 Azure 中,控制器的操作方法是通过 AJAX 执行的。
这里是抛出异常的代码:
public class BlacklistService : IBlacklistService
{
public bool Verify(string blacklist, string message)
{
if (string.IsNullOrEmpty(blacklist)) return true;
var split = blacklist.ToLower().Split(';'); // exception is thrown here
return !split.Any(message.Contains);
}
}
这里是堆栈跟踪的相关部分:
at System.MulticastDelegate.ThrowNullThisInDelegateToInstance()
at System.MulticastDelegate.CtorClosed(Object target, IntPtr methodPtr)
at MyApp.Business.Services.BlacklistService.Verify(String blacklist, String message)
at MyApp.Business.Services.ContactMessageFactory.GetVerifiedStatus(String mensagem)
at MyApp.Business.Services.ContactMessageFactory.GetMailMessage(ContactForm contactForm)
at MyApp.Business.ContactEmailService.Send(ContactForm contactForm)
有人能找出这个异常的可能原因吗?提前致谢。
消息为空时失败。可以用这个
return !split.Any(part => (message != null && message.Contains(part)));
问题在于 message
实际上是 null
。您可以很容易地重现它:
void Main()
{
Verify("hello", null);
}
public bool Verify(string blacklist, string message)
{
if (string.IsNullOrEmpty(blacklist)) return true;
var split = blacklist.ToLower().Split(';'); // exception is thrown here
return !split.Any(message.Contains);
}
发生的事情是 message.Contains
通过方法组转换传递给 Func<string, bool>
构造函数,它看起来像这样:
Func<string, bool> func = ((string)null).Contains;
return !split.Any(func);
这就是导致 MulticastDelegate
发疯的原因。在生成的IL中也可以看到:
IL_0028: ldftn System.String.Contains
IL_002E: newobj System.Func<System.String,System.Boolean>..ctor
IL_0033: call System.Linq.Enumerable.Any
为了避免这种情况发生,请确保您也对消息进行空检查:
public bool Verify(string blacklist, string message)
{
if (string.IsNullOrEmpty(blacklist)) return true;
if (string.IsNullOrEmpty(message)) return false;
var split = blacklist.ToLower().Split(';'); // exception is thrown here
return !split.Any(message.Contains);
}
具有空 this
的委托是最后使用的方法 string.Contains()
,它使用您的 message
变量作为 this
指针。换句话说,在 message
为空的地方进行了调用。