代码之家  ›  专栏  ›  技术社区  ›  burnt1ce

C:如何在接口中声明一个方法,以返回一个类用[serializable()]属性标记的对象?

c#
  •  1
  • burnt1ce  · 技术社区  · 16 年前

    在C中,如何在接口中声明一个方法来返回一个类被[serializable()]属性标记的对象?

    4 回复  |  直到 16 年前
        1
  •  3
  •   Sam Harwell    16 年前

    不能。如果您对此有问题,那么在运行时的早期,您可以使用反射来获取所有类型的列表,从这些筛选到实现这些类型的列表。 IYourInterface . 检查其中的每一个属性是否为必需属性,如果找不到异常,则抛出异常。

    编辑: 更好的检查是确保类型是可序列化的。C编译器使用 [Serializable] 属性来确定是否使用可序列化的cli内部标志标记该类型。一种类型的 必须有 [可序列化] 属性,以便CLI对其进行序列化。

    Type t = ...;
    if (typeof(IYourInterface).IsAssignableFrom(t) && !t.IsSerializable)
    {
        throw new TypeLoadException(string.Format(
            "The type {0} implements IYourInterface but is not serializable",
            t));
    }
    

    尽量避免上述检查,尤其是在生产代码中。如果您是第三方组件提供商,那么 清晰地记录 要求和 信任 您的客户应该遵循它(并且如果他们以后遇到问题,请相信他们能够在内部理解/使用类似的方法)。

        2
  •  4
  •   JaredPar    16 年前

    不幸的是,你不能这么做。接口签名只能在实现程序上强制执行本质上与类型相关的信息。您要做的是在实现程序上强制附加属性信息。这在元数据中不可表示,无法实现。

    可以强制实施者返回 ISerializable . 但是,对于使用 Serializable 属性。它们只是可序列化的,但不实现 可分割的 .

    我仍然在加快代码契约的速度,但似乎它们可以用契约类来执行。不过,它最终可能只是一个运行时强制执行。

        3
  •  0
  •   Paul Keister    16 年前

    这是不可能的。属性用于标记属性、方法和类,以便在通过反射检查编译的代码时可以发现该属性。编译器对属性的了解程度是,如果遇到一个属性,它将嵌入一个属性。但是属性不属于类型系统,因此也不属于接口定义。

    如果您期望一个可序列化的对象,那么您必须用反射来验证这个运行时,而不是编译时。

        4
  •  0
  •   Mathlec    16 年前

    以下代码将被编译,但我不知道它是否符合您的需要:

    public interface Test<T>
        where T : System.Runtime.Serialization.ISerializable
    {
        T method();
    }
    
    public class TestObject : System.Runtime.Serialization.ISerializable
    {
    
        #region ISerializable Membres
    
        public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
        {
            throw new NotImplementedException();
        }
    
        #endregion
    }
    
    public class TestClass : Test<TestObject>
    {
        #region Test<TestObject> Membres
    
        public TestObject method()
        {
            throw new NotImplementedException();
        }
    
        #endregion
    }