关于类的类型T的成员变量调用扩展方法(Calling an extension method on

2019-10-19 00:08发布

下面给出扩展方法:

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”

Answer 1:

因为这是不可能的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#编译器知道valueGuid在编译时。


下面的方式将工作,但它会打败“仿制药”的地步。 不还建议。 要如何做我举一个例子

public void Serialize(StringWriter sw_)
{
    if (typeof (T) == typeof (Guid))
    {
        ((Guid)(object)value).Serialize(sw_);
    }
}


Answer 2:

有没有办法申请的限制,使得“ 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);
    }
}

该适配器包装给定类型的实例,并公开了一种序列化。 请注意, TField<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);
        }
    }
}

无需仿制药了。 泛型类型强制执行安全和我们扔那了。



Answer 3:

我猜你会写一堆的每一个类型的扩展名(串行器)的方法。 这是可能的,但也有一些反射魔法。

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_);
    }

}


Answer 4:

在Field类问题是,T是一个通用的类型和它,在这一点上,是“未知”,从而扩展方法将不被显示为延伸方法是一个具体类型为GUID的。 你也许需要检查,看看T是GUID的,如果是这样,中投以GUID然后将允许您调用扩展方法 - 所以不知道,它甚至会编译。

作为在类Foo你的最后一个例子 - 是uID一个GUID? 如果是这样你输入您的分机类存在的项目和命名空间? 如果没有 - 你应该那么它会显示出来。



文章来源: Calling an extension method on a member variable of type T of class