2016-06-02 3 views
0

Я возился с скомпилированными делегатами и пытался вызвать 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); 
    } 

< редактировать: мне нужно, чтобы вернуться (бодрствует) и сделать эту попытку исправить ряд параметров. Не совсем то, на что я надеялся, в идеале я бы хотел использовать только параметр типа и сериализованную строку. Кроме того, утка говорит напоминает мне bug talk. :)

Aanyway, я все еще в поисках корневой исправления, а не только лейкопластырь ...

< редактировать 2: Теперь корень исправить, как представляется, в моем мозгу и понять, что нужен экземпляр для метода экземпляра или статический метод. Я думаю, что у меня были утки, которые выстроились в очередь и посчитали после хороших закрытых глаз. Спасибо, Eric.

ответ

9

Кто-нибудь знает починку к моему коду

Показать программиста, где ошибка в том, что они исправить ошибку. Научите программиста, как найти ошибку, и они перестают публиковать свой код ошибки для других людей, чтобы отлаживать их, сохраняя все время.

Получить резиновую утку. Прочтите эту строку вслух к утке.

var deserializeFuncParameterValue = Expression.Parameter(typeof(T), "DeserializeFuncParameterValue");     

Теперь прочтите эту строку громко к утке.

Deserialize = Expression.Lambda<Func<string, T>>(deserializeCall, deserializeFuncParameterValue, deserializeArgument).Compile(); 

Теперь объясните, как утка утка в полном неведении деревьев выражений почему это то, что код правильный. Так как код не правильный, вы не должны этого делать. Конкретная точка, в которой вы не можете сделать это, является либо ошибкой, либо точкой, где есть правильный код, который вы не можете оправдать. В любом случае, вы узнали что-то о коде, и, вероятно, вы нашли ошибку.

Подсказка: Сообщение об ошибке не является ошибочным. Если вам нужно, прочитайте сообщение об ошибке вслух и утку.

(оригинальный плакат пренебрегли опубликовать сообщение об ошибке, которое «Неверное число параметров, поставляемых для лямбда-декларации».)

(и мозг)?

Резиновая утка отладки работает, потому что она заканчивается вокруг части вашего мозга, которая мешает вам найти ошибку.Ваш мозг хочет верить, что код, который вы написали, верен, и это буквально не позволяет вам увидеть очевидную проблему. Вы читаете код, ваши глаза глазуруют немного, и это «очевидно правильно». Ну нет, это не так.

Объяснение этого утка заставляет мозг пересмотреть неправильные предположения, которые побудили вас поверить, что неправильный код был «явно правильным».

Отметьте, что it works for mechanical engineering problems and stuffed ducks too.

+0

Может ли этот пример использоваться с чучелом котенком вместо резиновой утки? Мне не нравятся утки, они злые, и я не уверен, что результат будет верным с котенком ... – Gusman

+0

@Gusman: Попробуй, посмотри, работает ли он. Я слышал, что он работает с гигантскими чучелами-лосями. –

+0

Ничего себе, хорошо! Я собираюсь убить теперь лося и все, что нужно, чтобы проверить это! благодаря! – Gusman

Смежные вопросы