Я возился с скомпилированными делегатами и пытался вызвать 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.
Может ли этот пример использоваться с чучелом котенком вместо резиновой утки? Мне не нравятся утки, они злые, и я не уверен, что результат будет верным с котенком ... – Gusman
@Gusman: Попробуй, посмотри, работает ли он. Я слышал, что он работает с гигантскими чучелами-лосями. –
Ничего себе, хорошо! Я собираюсь убить теперь лося и все, что нужно, чтобы проверить это! благодаря! – Gusman