繁体   English   中英

声明泛型类型作为接口的属性?

[英]Declare a generic type as property of an interface?

我有一个Generic类型,用于提供对象的一些元数据以保持:

public class PersistedElementDefinition<T> where T: IPersistedObject{
    List<PersistedPropertyDefinition<T>> PropertiesToPersist {get;set;}
}

public class PersistedPropertyDefinition<T> where T: IPersistedObject{
        public Func<T, object> PropertyGetter{get;set;}
        public Action<T, object> PropertySetter {get;set;}
}

我的IPersistedObject可以给出他的定义

public interface IPersistedObject{
    PersistedElementDefinition<TypeOfTheImplementingType> Definition {get;}
}

我的想法是,如果我实现IPersistedObject我应该像这样实现它:

public class MyPersistedObject:IPersistedObject{
    PersistedElementDefinition<MyPersistedObject> Definition{get;}
}

当我坚持上课时,我有以下几点:

不能做到以下几点:

public interface IPersistedObject<T>{
    PersistedElementDefinition<T> Definition {get;}
}

因为:

  1. 它将允许拥有MyPersistedObject<SomeOtherObject
  2. 在某些时候,我收到一个对象,我应该能够看到它是否实现了IPersistedObject并对其进行了一些自定义操作。

对于2,这里有一个例子,如果我有一个Generic界面我面临什么样的问题:

public void Persist<T>(T objectToPersist)where T:IPersistedObject{
    ...
    foreach(PersistedPropertyDefinition<T> property in objectToPersist.PropertiesToPersist){
        object objectToSerialize = property.ObjectGetter(objectToPersist);
        if(objectToSerialize is IPersistedObject<___Don't know how to put something generic here___>){
            Persist((IPersistedObject<___Don't know how to put something generic here___>)objectToSerialize);
        }
    }
    ...
}

在c#中是否有可能声明一个具有实现类型的泛型属性的接口?

您可以使用奇怪的重复模板模式将其进一步锁定。 它不是防弹的,但假设你不是一个受虐狂,并且你不介意理论上可以创建违反你试图保证的不变量的界面的无意义实现,你可以这样做:

public interface IPersistedObject<T> where T : IPersistedObject<T>
{
    PersistedElementDefinition<T> Definition {get;}
}

public class PersistedElementDefinition<T> where T: IPersistedObject<T>
{
    ...
}

public class MyPersistedObject : IPersistedObject<MyPersistedObject>
{
    // Here, you are forced to implement a PersistedElementDefinition<MyPersistedObject>,
    // which presumably is the reason behind this whole song and dance

    PersistedDefinition<MyPersistedObject> Definition { get; }
}

正如您在开始时注意到的那样,问题在于您可以简单地定义public class MyPersistedObject : IPersistedObject<MyOtherPersistedObject> ,并最终破坏您尝试拼凑的合同,简单来说如下:

持久化对象必须具有gettable定义,该定义是其自身类型的持久元素定义

C#型系统根本没有配备来优雅地处理这个问题。 我的建议是尽早退出,在可能的情况下改变objectdynamic ,并学习如何避免某些编译时保证。

假设你愿意牺牲一些编译时安全性,你可以这样做:

class Program
{
    static void Main(string[] args)
    {
        var mpo = new MyPersistedObject();
        var ptp = mpo.Definition.PropertiesToPersist;
    }
}

public class PersistedElementDefinition<T> where T : IPersistedObject
{
    private readonly List<PersistedPropertyDefinition<T>> _propsToPersist = new List<PersistedPropertyDefinition<T>>();
    public List<PersistedPropertyDefinition<T>> PropertiesToPersist
    {
        get { return _propsToPersist; }
    }
}

public class PersistedPropertyDefinition<T> where T : IPersistedObject
{
    public Func<T, object> PropertyGetter { get; set; }
    public Action<T, object> PropertySetter { get; set; }
}

public interface IPersistedObject
{
    dynamic Definition { get; }
}

public class MyPersistedObject : IPersistedObject
{
    private readonly PersistedElementDefinition<MyPersistedObject> _definition = new PersistedElementDefinition<MyPersistedObject>();
    public dynamic Definition { get { return _definition; } }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM