我正在摆弄已编译的委托,并尝试使用编译委托调用以下类中的Serialize
和Deserialize
函数(不要介意名称)。我成功地拨打了Serialize
,但没有Deserialize
。问题似乎是我似乎不明白如何将string
参数传递给以下代码中的Func
对象。有没有人知道我的代码(和大脑)的修复?
public class SomeClass
{
public string SomeString { get; }
public SomeClass(string str)
{
SomeString = str;
}
public string Serialize()
{
return SomeString;
}
public SomeClass Deserialize(string str)
{
return new SomeClass(str + " - !!!!");
}
}
public class Program
{
private static class TypeSerializationCache<T>
{
public static readonly Func<T, string> Serialize;
public static readonly Func<string, T> DeserializeThatShouldBe;
public static readonly Func<T, string, T> DeserializeOriginalFixed;
static TypeSerializationCache()
{
const string SerializeFunctionToCall = "Serialize";
var serializeFuncParameterValue = Expression.Parameter(typeof(T), "serializeFuncParameterValue");
var serializeMethod = typeof(T).GetMethod(SerializeFunctionToCall, BindingFlags.Instance | BindingFlags.Public, null, new Type[] { }, null);
var serializeCall = serializeMethod != null ? (Expression)Expression.Call(serializeFuncParameterValue, serializeMethod) : Expression.Constant(default(T), typeof(T));
Serialize = Expression.Lambda<Func<T, string>>(serializeCall, serializeFuncParameterValue).Compile();
const string DeserializeCallFunction = "Deserialize";
var deserializeFuncParameterValue = Expression.Parameter(typeof(T), "DeserializeFuncParameterValue");
var deserializeMethod = typeof(T).GetMethod(DeserializeCallFunction, BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(string) }, null);
var deserializeArgument = Expression.Parameter(typeof(string), "deserializeArgument");
var deserializeCall = Expression.Call(deserializeFuncParameterValue, deserializeMethod, deserializeArgument);
DeserializeOriginalFixed = Expression.Lambda<Func<T, string, T>>(deserializeCall, deserializeFuncParameterValue, deserializeArgument).Compile();
//To my great dismay, the following throws.
DeserializeThatShouldBe = Expression.Lambda<Func<string, T>>(deserializeCall, deserializeFuncParameterValue, deserializeArgument).Compile();
}
}
public static void Main(string[] args)
{
var class11 = new SomeClass("XYZ");
var class12 = new SomeClass("123");
var class31 = TypeSerializationCache<SomeClass>.Serialize(class11);
var class32 = TypeSerializationCache<SomeClass>.Serialize(class12);
var class31d = TypeSerializationCache<SomeClass>.DeserializeOriginalFixed(class11, class31);
var class32d = TypeSerializationCache<SomeClass>.DeserializeThatShouldBe(class32);
}
&lt; edit:我需要回来(清醒)并尝试修复参数的数量。不是我希望的,理想情况下我只想使用type参数和序列化字符串。此外, duck talk 让我想起了bug talk。 :)
Aanyway,我仍然在寻找根本修复,而不仅仅是创可贴......
&lt; edit 2:现在,root修复程序似乎在我的大脑中,并且理解一个实例方法或静态方法需要一个实例。我想我的鸭子排成一排并计算好后闭嘴。我要感谢 Eric 。
答案 0 :(得分:9)
有没有人知道我的代码修复
向程序员展示错误,他们修复了错误。 教会程序员如何找到错误,并停止发布他们的错误代码供其他人调试,节省每个人的时间。
获得一只橡皮鸭。请大声读出大声这一行。
var deserializeFuncParameterValue = Expression.Parameter(typeof(T), "DeserializeFuncParameterValue");
现在快速阅读大声这一行。
Deserialize = Expression.Lambda<Func<string, T>>(deserializeCall, deserializeFuncParameterValue, deserializeArgument).Compile();
现在向鸭子解释鸭子完全不知道表达树为什么代码是正确的。由于代码不正确,您应该无法执行此操作。您无法执行此操作的具体点是错误,或者是您无法证明正确代码的点。无论哪种方式,你已经学到了一些关于代码的东西,可能你已经找到了这个bug。
提示:错误消息没有错误。如果需要,也请向鸭子大声朗读错误信息。
(原始海报忽略了发布错误消息,即“为lambda声明提供的参数数量不正确”。)
(和大脑)?
橡皮鸭调试是有效的,因为它可以阻止你发现这个错误。你的大脑想要相信你写的代码是正确的,它实际上不允许你看到明显的问题。你读了代码,你的眼睛釉了一下,这“显然是正确的”。不,不是。
向鸭子解释它会迫使你的大脑重新检查错误的假设,这些假设会让你相信错误的代码“显然是正确的”。
请注意it works for mechanical engineering problems and stuffed ducks too。