如何编写一个带有一个参数的委托?

Vek*_*ksi 0 .net c# reflection

我是用汇编代表摆弄,并试图调用SerializeDeserialize函数使用编译代表(不介意的名字)下面的类.我成功地打电话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);
    }
Run Code Online (Sandbox Code Playgroud)

<编辑:我需要回来(清醒)并尝试修复参数的数量.不是我希望的,理想情况下我只想使用type参数和序列化字符串.另外,鸭子谈话让我想起了bug.:)

Aanyway,我仍然在寻找根本修复,而不仅仅是创可贴......

<编辑2:现在,根修复似乎在我的大脑中,并且理解一个实例方法或静态方法需要一个实例.我想我的鸭子排成一排,并且在闭上眼睛之后计算好了.我要感谢Eric.

Eri*_*ert 9

有没有人知道我的代码修复

向错误所在的程序员展示,他们修复了这个bug. 教程序员如何找到错误,他们停止发布他们的错误代码供其他人调试,节省每个人的时间.

获得一只橡皮鸭.大声读出这条线给鸭子.

var deserializeFuncParameterValue = Expression.Parameter(typeof(T), "DeserializeFuncParameterValue");                
Run Code Online (Sandbox Code Playgroud)

现在大声读出这条线给鸭子.

Deserialize = Expression.Lambda<Func<string, T>>(deserializeCall, deserializeFuncParameterValue, deserializeArgument).Compile();
Run Code Online (Sandbox Code Playgroud)

现在向鸭子解释鸭子完全不知道表达树为什么代码是正确的.由于代码正确,您应该无法执行此操作.您无法执行此操作的具体点是错误,或者是您无法证明正确代码的点.无论哪种方式,你已经学到了一些关于代码的东西,可能你已经找到了这个bug.

提示:错误消息没有错.如果需要,也请向鸭子大声朗读错误信息.

(原始海报忽略了发布错误消息,即" 为lambda声明提供的参数数量不正确 ".)

(和大脑)?

橡皮鸭调试是有效的,因为它会阻止你的大脑部分阻止你找到bug.你的大脑想要相信你写的代码是正确的,它实际上不允许你看到明显的问题.你看了代码,你的眼睛釉了一下,这"显然是正确的".不,不是.

向鸭子解释它会迫使你的大脑重新检查错误的假设,这些假设会让你相信错误的代码"显然是正确的".

请注意,它也适用于机械工程问题和填鸭.