我有一个泛型类,它拥有一个类型为参数类型的成员 我希望只能通过它实现的接口之一访问该成员 我只想通过这个接口访问成员,而不是枚举它可能的所有具体类型的原因是因为有很多这些类型。
具体而言,我想在该代码中找到等效的第61行(这是编译错误):
using System;
using System.Linq;
/* Interfaces */
public interface IArgumentClass
{
void IArgumentClassMethod();
}
public interface ISpecialArgumentClass
{
void ISpecialArgumentClassMethod();
}
public interface IContainerClass
{
void IContainerClassClassMethod();
}
/* Argument types */
public class ArgumentClass0 : IArgumentClass
{
public void IArgumentClassMethod(){}
}
public class SpecialArgumentClass0 : IArgumentClass, ISpecialArgumentClass
{
public void IArgumentClassMethod(){}
public void ISpecialArgumentClassMethod(){}
}
public class SpecialArgumentClass1 : IArgumentClass, ISpecialArgumentClass
{
public void IArgumentClassMethod() { }
public void ISpecialArgumentClassMethod() { }
}
/* Container types */
public class GenericContainer<T> : IContainerClass
where T : IArgumentClass, new()
{
public T t = new T();
public void IContainerClassClassMethod() { }
}
public class NonGenericContainer : IContainerClass
{
public void IContainerClassClassMethod(){}
}
/* main program */
public class Test
{
public static void Main()
{
// Instantiate
IContainerClass[] containers =
{
new GenericContainer<ArgumentClass0>(),
new GenericContainer<SpecialArgumentClass0>(),
new GenericContainer<SpecialArgumentClass1>(),
new NonGenericContainer()
};
// We want to call IContainerClassClassMethod methods on all instances:
foreach (IContainerClass container in containers)
container.IContainerClassClassMethod();
// We want to call ISpecialArgumentClassMethod on instances where it's possible:
foreach (IContainerClass container in containers)
{
if (container.GetType().IsGenericType && container.GetType().GetGenericTypeDefinition() == typeof(GenericContainer<>))
{
foreach (Type typeArgument in container.GetType().GetGenericArguments())
{
if (typeArgument.GetInterfaces().Contains(typeof(ISpecialArgumentClass)))
{
// Next line is a compilation error. How can I get a similar result?
GenericContainer<ISpecialArgumentClass> mySpecializedClassWithSpecialArgument = container as GenericContainer<ISpecialArgumentClass>;
mySpecializedClassWithSpecialArgument.t.ISpecialArgumentClassMethod();
}
}
}
}
}
}
注意:您可以分叉和编辑代码here。
答案 0 :(得分:2)
您收到编译错误,因为ISpecialArgumentClass
不是IArgumentClass
类型,但您的GenericClass
要求完全相同。
要解决这个问题,您可以引入一个空接口,作为两个参数类的基础:
首先,修改你的界面声明:
public interface IArgumentClassBase
{
}
public interface IArgumentClass : IArgumentClassBase
{
String GetNormalString();
}
public interface ISpecialArgumentClass : IArgumentClassBase
{
String GetSpecialString();
}
...然后像这样修改你的泛型类声明:
public class GenericClass<T> : IContainerClass
where T : IArgumentClassBase, new()
然后你的其余代码应该有用......
答案 1 :(得分:1)
一个非常简单的解决方案就是将其转换为动态 - 你知道它有一个t
字段,所以这应该是安全的。
if (typeArgument.GetInterfaces().Contains(typeof(ISpecialArgumentClass)))
{
dynamic mySpecializedClassWithSpecialArgument =
mySpecializedClass as dynamic;
ISpecialArgumentClass specialArgumentClass = mySpecializedClassWithSpecialArgument.t;
Console.WriteLine(specialArgumentClass.GetSpecialString());
}
我尝试在ideone中编辑它,但它无法编译。我怀疑它的目标是.NET的旧版本 - 动态是在.NET 4(VS 2010)中引入的。但是,我已经在2013年对代码进行了测试,但它确实有效。