下面给出扩展方法:
public static class Ext
{
public static void Serialize(this Guid guid_, StringWriter sw_)
{
sw_.Write(guid_.ToString("B"));
}
}
和类:
public class Field<T>
{
public T value;
public void Serialize(StringWriter sw_)
{
value.Serialize(sw_);
}
}
我想做到以下几点,但不能完全弄清楚:
public class Foo
{
public Field<Guid> uid;
public Foo()
{
// assume StringWriter object sw;
uid.Serialize(sw);
}
}
显然,现实生活中的情况比较复杂,这仅仅是一个裸机的例子。
编辑
编译器错误:
错误CS1928:“T”不包含关于“序列化”和最好的扩展方法过载“Ext.Serialize(的System.Guid,StringWriter的)”的定义有一些无效参数
错误CS1929:实例参数:无法从“T”转换成“的System.Guid”
因为这是不可能的T
不肯定在编译时是否已知Guid
与否。
但是你可以做这样的事情
public class GuidField : Field<Guid>
{
public override void Serialize(StringWriter sw_)//Assume we have made base class method virtual
{
value.Serialize(sw_);
}
}
这工作,因为C#编译器知道value
是Guid
在编译时。
下面的方式将工作,但它会打败“仿制药”的地步。 不还建议。 要如何做我举一个例子
public void Serialize(StringWriter sw_)
{
if (typeof (T) == typeof (Guid))
{
((Guid)(object)value).Serialize(sw_);
}
}
有没有办法申请的限制,使得“ T
只会是有定义的扩展方法类型”。
如果你确实需要使用泛型这一点,你必须创建一个可序列化,这样每种类型的适配器:
public static class Ext
{
public static void Serialize(this Guid guid_, StringWriter sw_)
{
sw_.Write(guid_.ToString("B"));
}
}
public class Field<T> where T: ISerializableField
{
public T value;
public void Serialize(StringWriter sw_)
{
value.Serialize(sw_);
}
}
public interface ISerializableField
{
void Serialize(StringWriter sw);
}
public class SerializableGuid : ISerializableField
{
private readonly Guid _guid;
public SerializableGuid(Guid guid)
{
_guid = guid;
}
public void Serialize(StringWriter sw)
{
_guid.Serialize(sw);
}
}
该适配器包装给定类型的实例,并公开了一种序列化。 请注意, T
在Field<T>
现在只能与适配器的情况下ISerializableField
-现在Field<T>
肯定知道的所有实例T
可以被序列化。
关于这一点,你就不需要扩展方法了,该适配器可以执行序列本身。 除非你的代码的其他部分也将要序列化一个GUID。
编辑
如果避免创建可序列化是你的首要任务各类型的类,你不介意失去类型安全,你可以使用动态invokation:
public class Field
{
private dynamic Value { get; set; }
public void Serialize(StringWriter sw)
{
try
{
Value.Serialize(sw);
}
catch (RuntimeBinderException ex)
{
throw new InvalidOperationException(string.Format("Instance of type {0} does not implement a Serialize method", Value.GetType()), ex);
}
}
}
无需仿制药了。 泛型类型强制执行安全和我们扔那了。
我猜你会写一堆的每一个类型的扩展名(串行器)的方法。 这是可能的,但也有一些反射魔法。
public static class Ext
{
public static void Serialize(this Guid guid_, StringWriter sw_)
{
sw_.Write(guid_.ToString("B"));
}
public static void Serialize(this int id, StringWriter sw_)
{
sw_.Write(id.ToString());
}
}
public class Field<T>
{
public T value;
private static Lazy<Action<T, StringWriter>> _serializer = new Lazy<Action<T, StringWriter>>(() => (Action<T, StringWriter>)Delegate.CreateDelegate(typeof(Action<T, StringWriter>), typeof(Ext), "Serialize"), true);
public void Serialize(StringWriter sw_)
{
_serializer.Value(value, sw_);
}
}
在Field类问题是,T是一个通用的类型和它,在这一点上,是“未知”,从而扩展方法将不被显示为延伸方法是一个具体类型为GUID的。 你也许需要检查,看看T是GUID的,如果是这样,中投以GUID然后将允许您调用扩展方法 - 所以不知道,它甚至会编译。
作为在类Foo你的最后一个例子 - 是uID一个GUID? 如果是这样你输入您的分机类存在的项目和命名空间? 如果没有 - 你应该那么它会显示出来。