Geo*_*sen 5 c# generics containers interface self-reference
好的,这就是我想做的.
Class Container<T>
{
T contained;
public void ContainObject(T obj)
{
contained = obj;
if(/*Magical Code That Detects If T Implemtns IContainableObject*/)
{
IContainableObect c = (IContainableObject)obj;
c.NotifyContained(self);
}
}
}
interface IContainableObject
{
public void NotifyContained(Container<REPLACE_THIS>);//This line is important, see below after reading code.
}
Class ImplementingType : IContaiableObject
{
public Container<ImplementingType> MyContainer;
public void NotifyContained(Container<ImplmentingType> c)
{
MyContainer = c;
}
}
Class Main
{
public static void Main(args)
{
ImplementingType iObj = new ImplementingType();
Container<ImplementingType> container = new Container();
container.ContainObject(iObj);
//iObj.MyContainer should now be pointing to container.
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,总结一下上面的例子,我有一个类型为T的通用包装类型.我希望该包装类型能够通知它所包含的任何内容(包含其自身的副本!)如果包含的对象实现了具体的界面(这一点,我知道怎么做)
但它变得棘手!为什么?好吧因为容器泛型需要有一个类型.
还记得重要的一句吗?
如果REPLACE_THIS是IContainableObject,那么接口的所有实现者都必须使用IContainerObject,而不是NotifyContained方法中实现类的名称.
由于显而易见的原因,使用ImplementingType作为接口内容器的类型更加糟糕!
所以我的问题是,我该怎么做才能使REPLACE_THIS代表实现接口的对象的类?
class Container<T>
{
T contained;
public void ContainObject(T obj)
{
contained = obj;
var containable = obj as IContainableObject<T>;
if(containable != null)
{
containable.NotifyContained(this);
}
}
}
interface IContainableObject<T>
{
void NotifyContained(Container<T> c);
}
class ImplementingType : IContainableObject<ImplementingType>
{
public Container<ImplementingType> MyContainer;
public void NotifyContained(Container<ImplementingType> c)
{
MyContainer = c;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:添加具有通用约束的版本
interface IContainer<T>
{
void ContainObject(T obj);
}
class Container<T> : IContainer<T> where T : IContainableObject<T>
{
T contained;
public void ContainObject(T obj)
{
contained = obj;
contained.NotifyContained(this);
}
}
interface IContainableObject<T>
{
void NotifyContained(IContainer<T> c);
}
class ImplementingType : IContainableObject<ImplementingType>
{
public IContainer<ImplementingType> MyContainer;
public void NotifyContained(IContainer<ImplementingType> c)
{
Debug.WriteLine("notify contained");
MyContainer = c;
}
}
Run Code Online (Sandbox Code Playgroud)