考虑以下课程
public static class ObjectHelper
{
public static Func<DateTime> Now = () => DateTime.Now;
public static Func<T, T> Clone = (obj) => Deserialize<T, T>(obj);
public static Func<TIn, TOut> Deserialize = (obj) => BsonSerializer.Deserialize<TOut>(obj.ToJson());
}
Clone
和Deserialize
声明无效。我用Google搜索了一下,但我似乎无法找到如何正确编写它们。我确信我错过了一些简单的事情。
我打算实现以下
Deserialize
方法的正文。目前它使用MongoDb C#驱动程序中的类。我希望能够将其切换为使用说JSON.Net。不要担心是否有正当理由这样做或有任何更好的方法。在我的现实世界问题中,我已经解决了这个问题并继续前进。我只是想学习是否可以像上面那样编写代码。 我添加了Now
来演示正常运行的代码。
答案 0 :(得分:1)
第一个Now
的作用原因是因为它不是通用的。
你在这里遇到了一些问题。
()
,只需使用变量名称解决问题的一些示例:
这是声明带参数的Lambda的正确方法:
// No input parameter, use ()
public static Func<DateTime> Now = () => DateTime.Now;
// Input parameter(s), just name them and put them after the = sign
public static Func<string, DateTime> Now = s => DateTime.Now;
为了使泛型类型能够使用方法,它必须实现一个接口和/或有一个约束,它继承了包含该方法的基类:
public interface HasJson
{
string ToJson();
}
public static class ObjectHelper<TIn, TOut>
where TIn : HasJson // now you can call ToJson() method on type TIn
您只需要2种泛型类型,TIn和TOut;不需要T,因为Clone采用相同的输入并返回与Deserialize相同的输出。这是一个有效的测试代码示例:
public static class ObjectHelper<TIn, TOut>
where TOut : class, new()
where TIn : HasJson
{
// This Lambda is not generic; it'll work wherever you put it :)
public static Func<DateTime> Now = () => DateTime.Now;
// Clone takes TIn, and returns the output of Deserialize, which is TOut;
// Therefore Clone and Deserialize will have the same generic type parameters
public static Func<TIn, TOut> Clone = obj => Deserialize(obj);
// calling obj.Json only possible due to where TIn: HasJson constraint above
public static Func<TIn, TOut> Deserialize = obj => FakeBSON(obj.ToJson());
// Just to test a method call in the generic lambda, meant to mimic what BSONSerializer
// does and allow my test code to compile without having BSONSerializer available
static TOut FakeBSON(string json)
{
var res = new TOut();
return res;
}
}