मैं सिस्टम के साथ एक अभिव्यक्ति बना रहा हूं और संकलित कर रहा हूं। Ling.Expressions API। संकलन ठीक काम करता है, लेकिन कुछ मामलों में मुझे संकलित lambda चलाते समय अस्पष्ट NullReferenceExceptions या यहां तक कि System.Security.Verification अपवाद मिलता है। संदर्भ के लिए, इस प्रोजेक्ट का उद्देश्य एक .NET प्रकार के लिए कस्टम सीरिएलाइज़र फ़ंक्शन बनाना और संकलित करना है।अजीब अपवाद संकलित गतिशील रूप से निर्मित अभिव्यक्ति संकलित
निम्नलिखित एक अभिव्यक्ति है कि एक NullReferenceException फेंकता के लिए DebugInfo है:
.Lambda #Lambda1<System.Action`2[IO.IWriter,<>f__AnonymousType1`2[System.Int32[],System.Int32]]>(
IO.IWriter $writer,
<>f__AnonymousType1`2[System.Int32[],System.Int32] $t) {
.Block() {
.Invoke (.Lambda #Lambda2<System.Action`2[IO.IWriter,System.Int32[]]>)(
$writer,
$t.a);
.Invoke (.Lambda #Lambda3<System.Action`2[IO.IWriter,System.Int32]>)(
$writer,
$t.b)
}
}
.Lambda #Lambda2<System.Action`2[IO.IWriter,System.Int32[]]>(
IO.IWriter $writer,
System.Int32[] $t) {
.Block() {
.Invoke (.Lambda #Lambda4<System.Action`2[IO.IWriter,System.Int32]>)(
$writer,
.Call System.Linq.Enumerable.Count((System.Collections.Generic.IEnumerable`1[System.Int32])$t));
.Call IO.SerializerHelpers.WriteCollectionElements(
(System.Collections.Generic.IEnumerable`1[System.Int32])$t,
$writer,
.Lambda #Lambda3<System.Action`2[IO.IWriter,System.Int32]>)
}
}
.Lambda #Lambda3<System.Action`2[IO.IWriter,System.Int32]>(
IO.IWriter $writer,
System.Int32 $t) {
.Call $writer.WriteInt($t)
}
.Lambda #Lambda4<System.Action`2[IO.IWriter,System.Int32]>(
IO.IWriter $w,
System.Int32 $count) {
.Call $w.BeginWritingCollection($count)
}
अपवाद # करने के लिए कॉल Lambda3, जो WriteCollectionElements से बार-बार कहा जाता है के भीतर फेंक दिया है।
static void WriteCollectionElements<T>(IEnumerable<T> collection, IWriter writer, Action<IWriter, T> writeAction)
{
foreach (var element in collection)
{
writeAction(writer, element);
}
}
इस समारोह के अंदर डिबगिंग से, मैं निर्धारित किया है कि संग्रह, लेखक, writeAction, और तत्व सभी में गैर-शून्य कर रहे हैं जब अपवाद फेंक दिया जाता है: WriteCollectionElements के कार्यान्वयन इस प्रकार है। तर्क यह है कि मैं संकलित लैम्ब्डा के लिए गुजर रहा है:
new { a = new[] { 20, 10 }, b = 2 }
भी अजीब है कि अगर मैं ख संपत्ति को हटाने और मेरी serializer समारोह दोबारा बनाने के, सब कुछ ठीक काम करता है। इस मामले में serializer के लिए DebugInfo है:
.Lambda #Lambda1<System.Action`2[IO.IWriter,<>f__AnonymousType5`1[System.Int32[]]]>(
IO.IWriter $writer,
<>f__AnonymousType5`1[System.Int32[]] $t) {
.Block() {
.Invoke (.Lambda #Lambda2<System.Action`2[IO.IWriter,System.Int32[]]>)(
$writer,
$t.a)
}
}
.Lambda #Lambda2<System.Action`2[IO.IWriter,System.Int32[]]>(
IO.IWriter $writer,
System.Int32[] $t) {
.Block() {
.Invoke (.Lambda #Lambda3<System.Action`2[IO.IWriter,System.Int32]>)(
$writer,
.Call System.Linq.Enumerable.Count((System.Collections.Generic.IEnumerable`1[System.Int32])$t));
.Call IO.SerializerHelpers.WriteCollectionElements(
(System.Collections.Generic.IEnumerable`1[System.Int32])$t,
$writer,
.Lambda #Lambda4<System.Action`2[IO.IWriter,System.Int32]>)
}
}
.Lambda #Lambda3<System.Action`2[IO.IWriter,System.Int32]>(
IO.IWriter $w,
System.Int32 $count) {
.Call $w.BeginWritingCollection($count)
}
.Lambda #Lambda4<System.Action`2[IO.IWriter,System.Int32]>(
IO.IWriter $writer,
System.Int32 $t) {
.Call $writer.WriteInt($t)
}
मैं विंडोज 7 पर .NET फ्रेमवर्क 4 (कम से कम है कि अपने निर्माण लक्ष्य है) चला रहा हूँ, वी.एस. एक्सप्रेस सी # 2010
किसी को भी किसी भी विचार है डीबग करने का प्रयास करने के लिए क्या गलत हो सकता है या अगले चरण क्या हो सकते हैं? अगर इससे मदद मिलेगी तो मुझे अधिक जानकारी पोस्ट करने में खुशी होगी।
संपादित करें: मैंने तब से (मेरे ज्ञान के लिए) इस बग के आसपास अपना रास्ता खोज लिया है, हालांकि मुझे यह समझने के करीब नहीं है कि ऐसा क्यों होता है।
MethodInfo writeCollectionElementsMethod = // the methodInfo for WriteCollectionElements with .MakeGenericMethod() called with typeof(T)
Expression<Action<IWriter, T> writeActionExpression = // I created this expression separately
ParameterExpression writerParameter, enumerableTParameter = // parameters of type IWriter and IEnumerable<T>, respectively
// make an expression to invoke the method
var methodCallExpression = Expression.Call(
instance: null, // static
method: writeCollectionElementsMethod,
arguments: new[] {
enumerableTParameter,
writerParameter,
// passing in this expression correctly would produce the weird error in some cases as described above
writeActionExpression
}
);
// make an expression to invoke the method
var methodCallExpressionV2 = Expression.Call(
instance: null, // static
method: writeCollectionElementsMethod,
arguments: new[] {
enumerableTParameter,
writerParameter,
// this did not cause the bug
Expression.Constant(writeActionExpression.Compile())
}
);
हालांकि, मैं अलग से हर अभिव्यक्ति संकलन पसंद नहीं आया, तो मैं WriteCollectionElements समारोह के साथ भाग पूरी तरह और बस कर समाप्त हो गया: कोड है कि भाव मैंने ऊपर पोस्ट किया है उत्पन्न में, मैं निम्नलिखित था अभिव्यक्ति के माध्यम से गतिशील लूप को गतिशील रूप से बनाना। लूप, अभिव्यक्ति। ब्रेक, आदि
इस प्रकार, अब मैं अवरुद्ध नहीं हूं, लेकिन अभी भी बहुत उत्सुक हूं।
अपवाद reproducable है हो सकता है? क्या यह हमेशा एक ही तत्व के लिए होता है? –
@DanielHilgarth हां, अपवाद हर बार होता है। यह हमेशा होता है जब एक ही तत्व को संसाधित करते हैं, इस मामले में 20. – ChaseMedallion
हो सकता है कि आप इस व्यवहार को पुन: उत्पन्न करने वाले न्यूनतम कोड के साथ एक छोटा सा नमूना अनुप्रयोग बना सकें? –